Gcc 如何';s GNU扩展函数在没有';t定义的GNU源

Gcc 如何';s GNU扩展函数在没有';t定义的GNU源,gcc,compilation,gnu,cpu-architecture,glibc,Gcc,Compilation,Gnu,Cpu Architecture,Glibc,我在不同的平台上测试GNU扩展功能,如“wcstoq”。 起初,我没有使用D_GNU_SOURCE编译testcase,因此我得到了如下编译警告: wcstoq.c:31:12: warning: implicit declaration of function 'wcstoq'; did you mean 'wcstol'? [-Wimplicit-function-declaration] retval=wcstoq(nptr,endptr,base); ^

我在不同的平台上测试GNU扩展功能,如“wcstoq”。 起初,我没有使用D_GNU_SOURCE编译testcase,因此我得到了如下编译警告:

wcstoq.c:31:12: warning: implicit declaration of function 'wcstoq'; did you mean 'wcstol'? [-Wimplicit-function-declaration]
     retval=wcstoq(nptr,endptr,base);
            ^~~~~~
            wcstol
当我使用gdb调试这个testcase时,它将进入正确的函数,这与我定义的案例_GNU_SOURCE相同。 但是当我没有定义_GNU_源代码时,函数出错了

例如:

当我在x86_64中测试超出范围的情况时,它应该设置
retval=LLONG_MAX(0x7FFFFFFFFFFFFFFF)
,但实际上它设置了
retval=-1(0xffffffffffffff)
。 当我在其他平台ppc中测试它时,结果也让我感到困惑,它实际上设置了
retval=0x000000007FFFFFFF
。 当我定义
\u GNU\u SOURCE
时,函数在x86\u 64和ppc中运行正常,它都返回
LLONG\u MAX(0x7fffffffffffff)

我的问题是:

1为什么我没有定义
\u GNU\u SOURCE
,但gcc仍然可以找到正确的函数

2为什么即使gcc找到了正确的函数,该函数也失败了,在某些情况下该函数仍然可以使用,但在其他情况下它出错了

3为什么不同平台的功能失效结果不同,架构平台或其他因素如何影响不同的结果

4使用GNU扩展功能的正确方法


太棒了

隐式函数声明是默认启用的GCC扩展,它使用返回类型
int
,但是函数定义为返回
long
。有了这样的类型不匹配,任何事情都可能发生。在实践中,结果取决于调用约定,这就是为什么它们在不同的体系结构中有所不同

您应该真正使用
-Werror=隐式函数声明进行编译(或使用C++)。隐式函数声明在大约二十年前(在ISO/IEC 9899:1999中)就已经从C中删除了,但是我们仍然无法更改GCC默认值,因为太多的autoconf检查会中断,导致软件意外丢失功能


(我想你是想在你的问题中写
retval
,而不是
errno

在你展示的例子中没有原型定义,因此编译器不知道参数的大小(或数量)。外部符号是存在的,因为它不是宏或内联符号。我认为4)的最佳答案是您应该定义
\u GNU\u SOURCE
,以使库头包含GNU扩展的原型。在没有声明的情况下,编译器假定返回类型为
int
。谢谢,@PeterCordes,您是否知道关于隐式声明函数行为的更多信息,不仅包括返回类型,还包括一些输入或输出参数,这是否意味着此函数的行为不可预测或未定义?特别是对于GNU扩展函数?谢谢,@ThomasDickey但我感到困惑和好奇的是,为什么即使没有定义函数也可以调用它?GNUāSOURCE,为什么函数的行为或输出在不同的平台上不一样?值得一提的是,ISO C89中允许隐式声明。但是,是的,在后来的ISO C标准(和C++)中,这是不允许的,并且同意这通常是个坏主意。即使没有
-Wall
,GCC也会发出警告,这是有原因的。