1

The following program gives an unexpected output .

#include<stdio.h>
int main()
{
    int a=10,b=20;

    printf("a=%d",a);
    printf(" b=%d");
    printf(" %d");
    return 0;
}

Why does the above code print: a=10 b=10 10

The output is same even if I declare b before a, or make 'a' register variable.

According to this post - Behaviour of printf when printing a %d without supplying variable name, a random value from the current stack is printed. But if that was the case, then changing the declaretion styles would result in different results.

So, what is actually happening here?

Community
  • 1
  • 1
Nilendu
  • 356
  • 4
  • 13
  • 6
    Undefined behavior is happening. Don't do it and don't bother finding a meaning in it. – Andrey Jul 02 '14 at 11:57
  • Ok. I got you. Thanks. But still expecting a satisfactory answer. :) – Nilendu Jul 02 '14 at 12:03
  • 3
    For a better answer, you would have to check the source code of your compiler, because your compiler is free to do anything it wants. – chepner Jul 02 '14 at 12:08
  • Function `printf` simply reads the 4 bytes that are located in the stack, immediately after the first argument (a pointer to the constant string that `printf` was called with). So the function simply prints whichever value is located in those 4 bytes. I'm reluctant to publish this as a formal answer, since most SO users are in love with the term *undefined behavior*... – barak manos Jul 02 '14 at 12:11
  • possible duplicate of [Behaviour of printf when printing a %d without supplying variable name](http://stackoverflow.com/questions/437816/behaviour-of-printf-when-printing-a-d-without-supplying-variable-name) – EvilTeach Jul 02 '14 at 12:37

2 Answers2

4

Function calls are designed so that arguments are always in a pre-defined place. Some older architectures put the arguments on the stack, most new architectures put the arguments in registers.

What's happening here is that the you overwrite the first argument to all the function calls to printf, but the second argument happens to stay unmodified. It's just luck though, anything could have overwritten the place on the stack or the register where the second argument is.

This is the core of undefined behavior in C. Anything could have happened, but usually you can reason about what actually happened. And that's why undefined behavior is so dangerous. Often you end up with behavior that seems predictable and then a minor operating system update or compiler update will change the behavior completely.

Art
  • 19,807
  • 1
  • 34
  • 60
2

put pointer to "a=%d" on the stack, put a on the stack, call printf(), reduce stack-pointer. Then put pointer to " b=%d" on the stack, call printf(), voila, a is still on the stack

Peter Miehle
  • 5,984
  • 2
  • 38
  • 55
  • What is `a` still doing on the stack? It should be removed after 1st `printf` – Andrey Jul 02 '14 at 12:04
  • 4
    @Andrey: Nothing is “removed” from the stack (what should this mean? Overwriting the value? Why should you do so? And with what value?) As long as the location where `a` happened to be stored at isn't reused the value resides there. – mafso Jul 02 '14 at 12:09
  • This may be true of some, maybe many, compilers, but it is by no means required to be true. – chepner Jul 02 '14 at 12:10
  • @chepner: true; a compiler may use registers, for example. But then again, UB = UB, and any rationale to an "expected" result can only be found by examining the compiler. – Jongware Jul 02 '14 at 12:12
  • @Jongware Yes, I said as much in my comment to the question. My point here is that there is no way to provide a *factual* answer without knowing the *exact* compiler being used. – chepner Jul 02 '14 at 12:13
  • @mafso for example if a is register variable, so before printf it is `push`ed onto stack and later `pop`ed. – Andrey Jul 02 '14 at 13:46
  • 2
    @Andrey Popping from the stack usually doesn't overwrite anything, just the stack pointer is adjusted, so the value still resides there. – mafso Jul 02 '14 at 13:58
  • @mafso true, but it can be overwritten with other stuff – Andrey Jul 02 '14 at 15:00