我在不同平台上测试了GNU扩展功能,例如“ wcstoq”。 一开始,我没有使用D_GNU_SOURCE编译测试用例,所以得到了如下编译警告:
wcstoq.c:31:12: warning: implicit declaration of function 'wcstoq'; did you mean 'wcstol'? [-Wimplicit-function-declaration]
retval=wcstoq(nptr,endptr,base);
^~~~~~
wcstol
当我使用gdb调试此测试用例时,它进入与我定义_GNU_SOURCE的情况相同的正确函数。 但是当我没有定义_GNU_SOURCE时,该函数就会出错。
例如:
当我在x86_64中测试超出范围的情况时,应设置retval= LLONG_MAX(0x7FFFFFFFFFFFFFFF)
,但实际上应设置retval= -1(0xFFFFFFFFFFFFFFFF)
。
当我在其他平台ppc上进行测试时,结果也使我感到困惑,它实际上设置了retval=0x000000007FFFFFFF
。
当我定义_GNU_SOURCE
时,函数在x86_64和ppc中运行正常,它们都返回LLONG_MAX(0x7FFFFFFFFFFFFFFF)
。
我的问题是:
1为什么当我没有定义_GNU_SOURCE
时,gcc仍然可以找到正确的函数?
2为什么即使gcc找到正确的功能,功能也失败了,在某些情况下仍可以使用该功能,但在其他情况下却出错了?
3为什么功能失败的结果在不同的平台上是不同的,架构平台或其他因素如何影响不同的结果?
4使用GNU扩展功能的正确方法?
谢谢!
答案 0 :(得分:1)
隐式函数声明是默认启用的GCC扩展,它使用返回类型int
,但是该函数定义为返回long long
。由于这种类型的不匹配,任何事情都可能发生。在实践中,结果取决于调用约定,这就是为什么它们在体系结构之间有所不同的原因。
您应该真正使用-Werror=implicit-function-declaration
进行编译(或使用C ++)。隐式函数声明是在20年前(在ISO / IEC 9899:1999中)从C中删除的,但是我们仍然不能更改GCC默认值,因为太多的autoconf检查会中断,从而导致软件意外丢失功能。
(我想您是在问题中写retval
而不是errno
。)