尝试在arm-none-eabi-gcc上使用tgmath.h中的cosdouble时未声明ccosl

问题描述

请考虑以下测试代码

#include <tgmath.h>

void test()
{
    double x=cos(4.5);
}

一样编译
arm-none-eabi-gcc test.c -c

在Ubuntu 18.04(gcc 6.3.1,newlib 2.4.0)上工作正常,但是在Ubuntu 20.04(gcc 9.2.1,newlib 3.3.0)上我遇到以下错误

In file included from test.c:1:
test.c: In function 'test':
test.c:5:14: error: 'ccosl' undeclared (first use in this function); did you mean 'ccosh'?
    5 |     double x=cos(4.5);
      |              ^~~
test.c:5:14: note: each undeclared identifier is reported only once for each function it appears in
test.c:5:14: error: argument 6 of '__builtin_tgmath' is not a function pointer

显然,cos的定义有所改变,因此现在提到ccosl,它在任何地方都没有声明。

如果我从tgmath.h更改为math.h,该错误将不再出现。当然,这只是解决方法,而不是解决方法,因为这样我就失去了floatdouble的类型通用性。

我的问题是:如何使其正常工作?我是否必须添加一些编译选项,还是仅仅是工具链中的错误

解决方法

看来,工具链版本之间的差异在于不同版本的tgmath cos宏的GCC实现。即,使用-E的{​​{1}}选项进行编译会在6.3.1中产生gcc的以下(已清理)扩展:

double x=cos(4.5)

在GCC 9.3.0中,扩展只是一个简单的函数调用:

double x=__builtin_choose_expr(__builtin_classify_type(4.5) == 9,__builtin_choose_expr(__builtin_types_compatible_p(__typeof__(__real__(4.5)),long double),ccosl(4.5),double) || __builtin_classify_type(__real__(4.5)) == 1,ccos(4.5),ccosf(4.5))
                                                    ),__builtin_choose_expr(__builtin_types_compatible_p(__typeof__(4.5),cosl(4.5),double) || __builtin_classify_type(4.5) == 1,cos(4.5),cosf(4.5))
                                                    )
                              );

两者之间的主要区别在于double x=__builtin_tgmath (cosf,cos,cosl,ccosf,ccos,ccosl,4.5); 不评估未选择的表达式(如the docs中所述),而__builtin_choose_expr是一个函数,需要所有参数有效。 而且看起来newlib从未在其__builtin_tgmath中包含ccosl,因此它似乎与较新版本的GCC不兼容。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...