I was having some problems with a sample code i was testing, since my abs function was not returning the correct result. abs(-2) was outputing -2 (this, by the way, is suposed to be the absolute value function, if that was unclear)
After getting a bit desperate, i eventually had the following code
#include <stdio.h>
unsigned int abs(int x) {
return 1;
}
int main() {
printf("%d\n", abs(-2));
return 0;
}
This does nothing useful but it serves to show my problem. This was outputing -2, when it was expected to output 1.
if i change the function name to something else (abs2 for example), the result is now correct. Also, if i change it to receive two arguments instead of one, it also fixes the problem.
My obvious guess: a conflict with the standart abs function. But this still doesn't explain why the output is -2 (it should be 2, if using the standart abs function). I tried checking the assembly output of both versions (with the function named abs and abs2)
Here's the diff output for both assemblys:
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
From what i understand, the first version (where the function is named abs) is simply discarding the function call, thus using the parameter x instead of abs(x)
So to sum up: why does this happen, especially since i couldn't find a way to get any sort of warning or error about this.
Tested on Debian Squeeze, ggc 4.4.5, and also on gcc 4.1.2
GCC is playing tricks on you due to the interplay of the following:
abs
is a built-in function;abs
to return unsigned int
while the standard (and built-in) abs
returns signed int
.Try compiling with gcc -fno-builtin
; on my box, that gives the expected result of 1
. Compiling without that option but with abs
declared as returning signed int
causes the program to print 2
.
(The real solution to this problem is to not use library identifiers for your own functions. Also note that you shouldn't be printing an unsigned int
with %d
.)
gcc
optimizes the call to abs()
to use its built-in abs()
. So if you use the -fno-builtin
option (or define your abs()
as returning int
), you'll notice you get the correct result. According to this (quoting):
GCC includes built-in versions of many of the functions in the standard C library. The versions prefixed with _builtin will always be treated as having the same meaning as the C library function even if you specify the -fno-builtin option. (see C Dialect Options) Many of these functions are only optimized in certain cases; if they are not optimized in a particular case, a call to the library function will be emitted.
Had you included stdlib.h
, which declares abs()
in the first place, you'd get an error at compile time.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With