GCCfunction名称冲突
我正在测试的示例代码有一些问题,因为我的abs函数没有返回正确的结果。 abs(-2)输出-2(顺便说一句,这是绝对值函数,如果不清楚的话)
在有点绝望之后,我最终得到了以下代码
#include unsigned int abs(int x) { return 1; } int main() { printf("%d\n", abs(-2)); return 0; }
这没有任何用处,但它可以显示我的问题。 当输出为1时,输出-2。
如果我将函数名称更改为其他内容(例如abs2),则结果现在是正确的。 此外,如果我将其更改为接收两个参数而不是一个,它也可以解决问题。
我明显的猜测:与标准absfunction发生冲突。 但这仍然无法解释为什么输出为-2(如果使用标准abs函数,它应为2)。 我试着检查两个版本的汇编输出(使用名为abs和abs2的函数)
这是两个组件的diff输出:
23,25c23,25 < .globl abs < .type abs, @function .globl abs2 > .type abs2, @function > abs2: 54c54 .size abs2, .-abs2 71c71,74 movl -4(%rbp), %eax > movl %eax, %edi > call abs2 > movl %eax, %edx
据我所知,第一个版本(函数名为abs)只是丢弃函数调用,因此使用参数x而不是abs(x)
总结一下:为什么会发生这种情况,特别是因为我无法找到一种方法来获得任何关于此的警告或错误。
在Debian Squeeze,ggc 4.4.5和gcc 4.1.2上测试过
由于以下各项的相互作用,海湾合作委员会正在对你耍花招:
-
abs
是一个内置函数; - 当标准(和内置)
abs
返回signed int
时,你声明abs
返回unsigned int
signed int
。
尝试使用gcc -fno-builtin
编译; 在我的盒子上,这给出了预期的结果1
。 编译没有该选项但abs
声明为返回signed int
会导致程序打印2
。
(这个问题的真正解决方案是不为自己的函数使用库标识符。另请注意,不应该使用%d
打印unsigned int
。)
gcc
优化对abs()
的调用以使用其内置的abs()
。 因此,如果您使用-fno-builtin
选项(或将您的abs()
定义为返回int
),您会注意到您获得了正确的结果。 根据这个 (引用):
GCC包含标准C库中许多function的内置版本。 即使指定了-fno-builtin选项,以_ builtin为前缀的版本也将被视为具有与C库函数相同的含义。 (参见C方言选项)许多这些function仅在某些情况下得到优化; 如果它们在特定情况下未被优化,则将发出对库函数的调用 。
如果你包含stdlib.h
,它首先声明abs()
,你会在编译时遇到错误。
听起来很像这个bug ,这是从2007年开始,并被注意到已修复。
你当然应该尝试编译没有GCC的内在函数,即在编译时传递-fno-builtin
(或者只是-fno-builtin-abs
来阻止abs()
)。