In the following C code:
#include <stdio.h>
int main(void){getchar();}
It produces the following asm:
main:
push rbp
mov rbp, rsp
# no extra instruction here when header is included
call getchar
mov eax, 0
pop rbp
ret
However, if I don't include stdio.h
in the file, then it still compiles, but adds in what looks like a random mov eax, 0
instruction:
Here is Compiler Explorer: https://godbolt.org/z/3fTcss. Is this just part of "undefined behavior", or is there a particular reason that the instruction before call getchar
is added there?
Without the header, gcc provides an implicit declaration of getchar
when you use it, as if you had previously declared
int getchar();
(This behavior was guaranteed by older versions of the C standard. Current versions make it undefined behavior to use a function which was not previously declared, but gcc still provides the old behavior as an extension.)
This declaration provides no information about the types of arguments which getchar
expects. (Remember that unlike in C++, a declaration with ()
doesn't declare a function as taking no arguments, but as taking unspecified arguments, leaving it up to the programmer to know what the function expects and pass the proper number and type of arguments.) For all the compiler knows, it could even be variadic, and per the x86-64 SysV ABI, variadic functions expect in al
the number of vector registers which are being used to pass in arguments. Here no vector registers are being used, so the compiler sets al
to 0
before the call. (It's slightly more efficient to actually zero all of rax
so it does that instead.)