The C standard allows the implementation to return any negative value. It also allows the implementation to do optimizations of library function calls as long as the result obeys the standard ... thus, implementations can optimize functions like strcmp
by generating inline machine instructions instead of calling a function. Extra optimizations are possible when arguments are constants. So the reason the results are different is because the optimizer happens to generate different code for some of the cases. A conforming program is not allowed to care which negative value is returned.
Edit:
On my system at the moment, the output is
-1
-3
-3
Here is the code the compiler generated that produced those results (obtained with gcc -S):
movl $-1, 4(%esp)
movl $LC2, (%esp)
call _printf
movl $LC1, 4(%esp)
movl 28(%esp), %eax
movl %eax, (%esp)
call _strcmp
movl %eax, 4(%esp)
movl $LC2, (%esp)
call _printf
movl 24(%esp), %eax
movl %eax, 4(%esp)
movl 28(%esp), %eax
movl %eax, (%esp)
call _strcmp
movl %eax, 4(%esp)
As you can see, there are only two strcmp
calls. The -1 result for the first comparison is produced at compile-time, because the compiler knows that "a" is less than "d". If I use -O, it produces this code:
movl $-1, 4(%esp)
movl $LC0, (%esp)
call _printf
movl $-1, 4(%esp)
movl $LC0, (%esp)
call _printf
movl $-1, 4(%esp)
movl $LC0, (%esp)
call _printf