There are 2 issues at hand: First is why doesn't the compiler issue an error about this bad call to printf()
, and second is why you get garbage output. I'll answer them one at a time.
printf()
is a tricky function. While most functions have a constant amount of arguments passed to them, printf()
is different.
For example, if we take this simple function:
int max(int a, int b) {
if (a > b) return a;
else return b;
}
You can see that this function always receives 2 arguments. This is also something that the compiler knows, and enforces when you compile you code. This is why a call such as max(4)
won't work. The compiler will see that we are passing max()
1 argument instead of 2 and it will issue an error.
printf()
is a function that takes a variable amount of arguments, and this amount is determined by the amount of format specifiers (things that start with %) in the format string. This means that the compiler cannot know at compile time if the amount of arguments that you passed to printf is enough (or maybe too much).
The reason that you get garbage printed is because of how functions read their input arguments. All input arguments for a function reside on the stack. These are pushed into the stack before the function is called and later addressed by the function. In this case, printf()
expects to have an extra argument besides the format string (because of the %d
), and so it looks in the address where its 2nd argument might have been. Alas, that argument wasn't passed, so it will actually look into a place in the stack that might contain anything else (a return address, a frame pointer, a local variable of an enclosing scope or other).
You can read more about how function calls work here.