how printf function work? [duplicate] - c++

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Undefined Behavior and Sequence Points
How the statement x=x++ + y++; executes to the value 3?
I was wondering how printf work in a case like this:
int i = 0;
printf("%4d%4d", i++, i);
Result is 0 1
in another case
int i = 0;
printf("%4d%4d", i, i++);
Result is 1 0

This has nothing to do with printf, and everything to do with the order in which the parameters are evaluated and the way the compiler executes your code. The behavior is undefined, and the results will depend on your compiler, calling convention, and phase of the moon.
In both your examples, the rules of pre/post incrementing are taking precedence. Your particular compiler understands that it must use the value of i before evaluating the increment, and is giving precedence to the parameter that invokes a function call over the one that doesn't. Your second usage of the variable i is causing the compiler to insert an intermediary statement in the process of calling printf,
It's important to note that i++ doesn't mean (as is commonly taught) "increment i after executing this line", it just means "increment i at some point after giving me its value, and before executing the next line". That's a lot of wiggle room for the compiler to do what is formally called "undefined behavior."
As #Als points out in a comment, you've managed to combine both undefined and unspecified behaviors in one line of code.

This is not due to printf it's due to you being in a case of undefined behaviour

Related

pre increment and post increment result discrepancy in MSdos and DevC++ compiler [duplicate]

This question already has answers here:
Is the output of printf ("%d %d", c++, c); also undefined?
(6 answers)
Closed 6 years ago.
I am unable to understand the below issues while pre-incrementing and post-incrementing a variable inside printf:-
code used in turbocpp compiler:-
#include<stdio.h>
main()
{
int i=0;
clrscr();
printf("%d %d %d",i,i++,++i);
getch();
return(0);
}
the output in MSdos Compiler is :- 2 1 1
but for the same program in DevC++ 5.11 the output is:- 2 1 2
1) My understanding is printf prints by taking left variable first and then moves to right.(i have verified it using 3 different variables.) So, according to that shouldn't the output be 0 0 2?
2) I tried with DevC++ to check the output of the same program but it gave a different result. Now I am really confused as what should be the output.
3) Also if I vary:- printf ("%d %d %d", i,++i,i++); the output is 2 2 0.
I am not getting what is going on here. Somebody Please help me to understand better...
Having two side effects on the same variable will give you an undetermined result, as each compiler is free to choose the order in which it evaluates the arguments.
1.9/15: If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a
value computation using the value of the same scalar object, the
behavior is undefined.
So it could for example be:
0,0,1 if evaluated left to right
2,1,1 if evaluated right to left
2,1,2 if pre-increment is done on i and stored in i, then i is loaded as second argument and post incremented, then i is taken ans third argument (the compiler assuming that preincrement was already done), and then i is taken as first argument.
But other combinations could also be plausible. And undefined behaviour means really undefined, so perhaps one day this could even crash (if one say a compiler would automatically generate parallel code and 2 cores access to the same variable in the same time)
C++ doesn't standardize the order in which function arguments are calculated, that's why results differ from compiler to compiler. See C++ Standard, section 5.2.2/8:
The order of evaluation of arguments is unspecified.

Post/pre increments in 'printf' [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
Output of multiple post and pre increments in one statement
Post-increment and pre-increment in 'for' loop
The following code snippet
int i=0;
printf("%d %d",i++,i++);
gives the output
1 0
I can understand that, but the following
int i=0;
printf("%d %d",++i,++i);
gives the output
2 2
Can someone explain me the second behavior?
Both printfs invoke undefined-behavior. See this : Undefined behavior and sequence points
Quoted from this link:
In short, undefined behaviour means
anything can happen from daemons
flying out of your nose to your
girlfriend getting pregnant.
For newbies : Don't ever try to modify values of your variables twice or more in a function call argument-list. For details, click here to know what it means. :-)
They're both undefined behaviour. Modifying the variable i more than once is undefined. Also, C++ or C? You need to make up your mind as the behaviour of pre-increment I believe is different between them.
You got what called 'undefined behaviour', because you are changing the same variable more than once between sequence points. Another compiler can give you different results.

How do we explain the result of the expression (++x)+(++x)+(++x)? [duplicate]

This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 25 days ago.
x = 1;
std::cout << ((++x)+(++x)+(++x));
I expect the output to be 11, but it's actually 12. Why?
We explain it by expecting undefined behaviour rather than any particular result. As the expression attempts to modify x multiple times without an intervening sequence point its behaviour is undefined.
As others have said, the C and C++ standards do not define the behaviour that this will produce.
But for those people who don't see why the standards would do such a thing, let's go through a "real world" example:
1 * 2 + 3 + 4 * 5
There's nothing wrong with calculating 1 * 2 + 3 before we calculate 4*5. Just because multiplication has a higher precedence than addition doesn't mean we need to perform all multiplication in the expression before doing any addition. In fact there are many different orders you validly could perform your calculations.
Where evaluations have side effects, different evaluation orders can affect the result. If the standard does not define the behaviour, do not rely on it.
This is actually undefined. C++ doesn't define explicitly the order of execution of a statement so it depends on the compiler and this syntax shouldn't be used.
The code snippet will invoke Undefined behavior in both C/C++.Read about Sequence Point from here.
In my opinion
cout<<((++x)+(++x)+(++x));
compiler first run prefix ++x so value of x becomes
x=2
now by ++x, x will become
x=3
after ++x
x=4
Now its time to add values of x
x+x+x=4+4+4
x+x+x=12

Undefined/unspecified? [duplicate]

This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
Why is i = ++i + 1 unspecified behavior?
Consider the following snippet :
int i=10;
printf("%d %d %d",i,++i,i--);
The order in which the arguments to a function are evaluated is unspecified in C/C++.So it lead to unspecified behavior.
Am I correct or missing something ? Please Explain.
EDIT:Well,some member believes it to be duplicate and this is an Undefined behaviour.Anyways,from C99:
6.5.2.2(10)
The order of evaluation of the function designator, the actual arguments, and
subexpressions within the actual arguments is unspecified, but there is a sequence point before the actual call.
So what would be the exact nomenclature now,Undefined or Unspecified ?
Yes, true.
I take it it's because on different platforms different machinery is employed to pass arguments and therefore parameters may be evaluated in different order.
What you're seeing is an example of where the C/C++ spec is undefined, so different compilers can do whatever they want. One compiler might execute the parameters in left to right order, another might do it in right to left order. It would be perfectly OK for a compiler to pick the order randomly.
The point that your source is trying to make is that you shouldn't rely on any order when passing parameters. For example if you had:
A(DoX(), DoY())
DoX and DoY can't rely on any side-effects of the other, because they're executed in an undefined order. To be perfectly explicit you'd want to do something like:
int x = DoX();
int y = DoY();
A(x, y);
For the majority of real-world production code you don't run into this situation very often, but it does happen every now and again.
Note that this is related to, but different from short circuit evaluation.

Post increment operator behavior [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Pre & post increment operator behavior in C, C++, Java, & C#
Here is a test case:
void foo(int i, int j)
{
printf("%d %d", i, j);
}
...
test = 0;
foo(test++, test);
I would expect to get a "0 1" output, but I get "0 0"
What gives??
This is an example of unspecified behavior. The standard does not say what order arguments should be evaluated in. This is a compiler implementation decision. The compiler is free to evaluate the arguments to the function in any order.
In this case, it looks like actually processes the arguments right to left instead of the expected left to right.
In general, doing side-effects in arguments is bad programming practice.
Instead of foo(test++, test); you should write foo(test, test+1); test++;
It would be semantically equivalent to what you are trying to accomplish.
Edit:
As Anthony correctly points out, it is undefined to both read and modify a single variable without an intervening sequence point. So in this case, the behavior is indeed undefined. So the compiler is free to generate whatever code it wants.
This is not just unspecified behaviour, it is actually undefined behaviour .
Yes, the order of argument evaluation is unspecified, but it is undefined to both read and modify a single variable without an intervening sequence point unless the read is solely for the purpose of computing the new value. There is no sequence point between the evaluations of function arguments, so f(test,test++) is undefined behaviour: test is being read for one argument and modified for the other. If you move the modification into a function then you're fine:
int preincrement(int* p)
{
return ++(*p);
}
int test;
printf("%d %d\n",preincrement(&test),test);
This is because there is a sequence point on entry and exit to preincrement, so the call must be evaluated either before or after the simple read. Now the order is just unspecified.
Note also that the comma operator provides a sequence point, so
int dummy;
dummy=test++,test;
is fine --- the increment happens before the read, so dummy is set to the new value.
Everything I said originally is WRONG! The point in time at which the side-affect is calculated is unspecified. Visual C++ will perform the increment after the call to foo() if test is a local variable, but if test is declared as static or global it will be incremented before the call to foo() and produce different results, although the final value of test will be correct.
The increment should really be done in a separate statement after the call to foo(). Even if the behaviour was specified in the C/C++ standard it would be confusing. You would think that C++ compilers would flag this as a potential error.
Here is a good description of sequence points and unspecified behaviour.
<----START OF WRONG WRONG WRONG---->
The "++" bit of "test++" gets executed after the call to foo. So you pass in (0,0) to foo, not (1,0)
Here is the assembler output from Visual Studio 2002:
mov ecx, DWORD PTR _i$[ebp]
push ecx
mov edx, DWORD PTR tv66[ebp]
push edx
call _foo
add esp, 8
mov eax, DWORD PTR _i$[ebp]
add eax, 1
mov DWORD PTR _i$[ebp], eax
The increment is done AFTER the call to foo(). While this behavior is by design, it is certainly confusing to the casual reader and should probably be avoided. The increment should really be done in a separate statement after the call to foo()
<----END OF WRONG WRONG WRONG ---->
It's "unspecified behavior", but in practice with the way the C call stack is specified it almost always guarantees that you will see it as 0, 0 and never 1, 0.
As someone noted, the assembler output by VC pushes the right most parameter on the stack first. This is how C function calls are implemented in assembler. This is to accommodate C's "endless parameter list" feature. By pushing parameters in a right-to-left order, the first parameter is guaranteed to be the top item on the stack.
Take printf's signature:
int printf(const char *format, ...);
Those ellipses denote an unknown number of parameters. If parameters were pushed left-to-right, the format would be at the bottom of a stack of which we don't know the size.
Knowing that in C (and C++) that parameters are processed left-to-right, we can determine the simplest way of parsing and interpreting a function call. Get to the end of the parameter list, and start pushing, evaluating any complex statements as you go.
However, even this can't save you as most C compilers have an option to parse functions "Pascal style". And all this means is that the function parameters are pushed on the stack in a left-to-right fashion. If, for instance, printf was compiled with the Pascal option, then the output would most likely be 1, 0 (however, since printf uses the ellipse, I don't think it can be compiled Pascal style).
C doesn't guarantee the order of evaluation of parameters in a function call, so with this you might get the results "0 1" or "0 0". The order can change from compiler to compiler, and the same compiler could choose different orders based on optimization parameters.
It's safer to write foo(test, test + 1) and then do ++test in the next line. Anyway, the compiler should optimize it if possible.
The order of evaluation for arguments to a function is undefined. In this case it appears that it did them right-to-left.
(Modifying variables between sequence points basically allows a compiler to do anything it wants.)
Um, now that the OP has been edited for consistency, it is out of sync with the answers. The fundamental answer about order of evaluation is correct. However the specific possible values are different for the foo(++test, test); case.
++test will be incremented before being passed, so the first argument will always be 1. The second argument will be 0, or 1 depending on evaluation order.
According to the C standard, it is undefined behaviour to have more than one references to a variable in a single sequence point (here you can think of that as being a statement, or parameters to a function) where one of more of those references includes a pre/post modification.
So:
foo(f++,f) <--undefined as to when f increments.
And likewise (I see this all the time in user code):
*p = p++ + p;
Typically a compiler will not change its behaviour for this type of thing (except for major revisions).
Avoid it by turning on warnings and paying attention to them.
To repeat what others have said, this is not unspecified behavior, but rather undefined. This program can legally output anything or nothing, leave n at any value, or send insulting email to your boss.
As a matter of practice, compiler writers will usually just do what's easiest for them to write, which generally means that the program will fetch n once or twice, call the function, and increment sometime. This, like any other conceivable behavior, is just fine according to the standard. There is no reason to expect the same behavior between compilers, or versions, or with different compiler options. There is no reason why two different but similar-looking examples in the same program have to be compiled consistently, although that's the way I'd bet.
In short, don't do this. Test it under different circumstances if you're curious, but don't pretend that there is a single correct or even predictable result.
The compiler might not be evaluating the arguments in the order you'd expect.