我在测试的示例代码中遇到了一些问题,因为我的 abs 函数没有返回正确的结果。 abs(-2) 输出 -2(顺便说一下,这应该是绝对值函数,如果不清楚的话)
在有点绝望之后,我最终有了以下代码
#include <stdio.h>
unsigned int abs(int x) {
return 1;
}
int main() {
printf("%dn", abs(-2));
return 0;
}
这没有任何用处,但它可以显示我的问题。这是输出 -2,而预期输出为 1。
如果我将函数名称更改为其他名称(例如 abs2),则结果现在是正确的。此外,如果我将其更改为接收两个参数而不是一个参数,它也可以解决问题。
我明显的猜测是:与标准腹肌功能冲突。但这仍然不能解释为什么输出是 -2(如果使用标准 abs 函数,它应该是 2)。我尝试检查两个版本的程序集输出(使用名为 abs 和 abs2 的函数)
下面是两个程序集的差异输出:
23,25c23,25
< .globl abs
< .type abs, @function
< abs:
---
> .globl abs2
> .type abs2, @function
> abs2:
54c54
< .size abs, .-abs
---
> .size abs2, .-abs2
71c71,74
< movl -4(%rbp), %edx
---
> 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 上测试
以下因素的相互作用,GCC 正在欺骗您:
-
abs
是一个内置函数; - 您声明
abs
返回unsigned int
而标准(和内置)abs
返回signed int
。
尝试使用 gcc -fno-builtin
编译 ; 在我的盒子上,这给出了1
的预期结果。在没有该选项的情况下进行编译,但abs
声明为返回signed int
会导致程序打印2
。
(这个问题的真正解决方案是不对自己的函数使用库标识符。另请注意,您不应打印带有%d
的unsigned int
。
gcc
优化了对abs()
的调用以使用其内置abs()
。因此,如果您使用 -fno-builtin
选项(或将abs()
定义为返回 int
),您会注意到您得到了正确的结果。据此(引用):
GCC 包括许多函数的内置版本 标准 C 库。以 _builtin 为前缀的版本将始终 被视为与 C 库函数具有相同的含义,甚至 如果指定 -FNO 内置选项。(请参阅 C 方言选项)多 这些功能仅在某些情况下进行优化;如果他们是 在特定情况下未优化,调用库函数 将被发出。
如果首先包含声明abs()
的 stdlib.h
,则会在编译时出现错误。
很像这个错误,它是从2007年开始的,并被记录为已修复。
当然,您应该尝试在没有GCC的内在的情况下进行编译,即在编译时传递-fno-builtin
(或只是-fno-builtin-abs
狙击abs()
)。