operator precedence problem? [duplicate] - c

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Compilers and argument order of evaluation in C++
i have a print statement like below...
int i=0;
printf("%d,%d,%d,%d,%d,%d",i++,i,++i,i--,++i,i);
according to precedence i++,i,++i,i--,++i,i should be evaluated like below step by step...
0,i,++i,i--,++i,i // after this i=1;
0,i,++i,1,++i,i // after this i=0;
0,i,++i,1,1,i // after this i=1;
0,i,2,1,1,i // after this i=2;
0,2,2,1,1,2 // after this i=2;
and final result as i think from this logic should be...
0,2,2,1,1,2
but i am getting 2,2,2,1,2,2 what is the reason behind this?
btw i m using visual c++ 2010...

That's undefined behavior. The order of evaluation of the arguments to a function is specifically left unspecified by the C and C++ language standards in order to let the compiler produce the most optimal machine code across a broad range of hardware.
You're not allowed to modify a variable more than once between sequence points. The language standard says that sequence points only come at particular points in your code, such as at the semicolons that delimit statements. There is a sequence point after the initial assignment int i=0;, there is a sequence point after printf returns, and there is a sequence point after all of the arguments to printf have been evaluated but before printf actually gets called, but there is not a sequence point in between the evaluation of each of the arguments.

Not.
The comma operator here:
a,b;
and the comma which separates functions arguments:
f(a,b);
are different.
Only real comma operator will be a sequence point and will order evaluation of left and right arguments (a and b expressions in my example).
And the comma between function arguments is not a sequence point and order of argument evaluation is undefined (even same compiler may evaluate them in different order in different call sites). Also, it is illegal (undefined behaviour) to change the same lvalue (i variable in your example) twice or more times in the part of program between sequence points. Every modification of same object must be separated by sequence point (e.g. with ;) from another modification of the same object.

The comma in your case is not the , operator that guarantees evaluation in sequence, but belongs to the function call syntax and the sequence in which function arguments are evaluated is undefined. So your code should surely exhibit undefined behaviour (which it seemingly does).

It's up to the compiler what code it generates. Evaluation order of the arguments of a function call is not defined.

Related

How exactly is the program running?

I am a beginner in C and I came across a code which went like this:
#include<stdio.h>
int main()
{
int k=35;
printf("%d %d %d",k==35,k=50,k>40);
return 0;
}
I tried to find the output without writing the code in my computer and 'actually' running it first. So here's how I figured out what the output might be:
In the precedence table, among assignment (==), equality (=) and greater than (>) operators, the greater than operator will be implemented first. So, initially, k=35 and thus k>40 is false (the integer thus will be 0). Next up is the equality operator (==). Now, k==35 is true initially. So this will return an integer 1. Finally, the assignment operator (=) will do its job, set the value of k to 50(and ultimately, returning 50) and the program will exit. Thus, based on this logic, I 'guessed' that final output will be like:
1 50 0
Now I ran the code in my IDE (I'm coming to my IDE a bit later) and the result it gave was:
0 50 0
So, my confusion is, in which order are the operators being implemented?
Any help or hints are very much welcome.
NOTE: I noticed a bit closer and found that the only way possible is: First the > operator does its job, then the = operator and finally, the == operator.
I changed my printf line a bit and wrote:
printf("%d %d %d",k==35,k>40,k=50);
Here, I found that the output was:
0 1 50
which, again was not according to what I 'guessed' initially with my logic.
I tried all the possible ordering of the syntax inside the printf() function. After looking at all those outputs, I doubt: Is the program being implemented in a right-to-left order here irrespective of the ordering in the precedence table?
NOTE: Regarding my IDE, I use Dev C++ 5.11. I use it as our instructor has advised us to use it for our course. As this IDE is not so much well-received among many others, I tried an online compiler, but the results are the same.
The behavior is undefined - the result is not guaranteed to be predictable or repeatable.
First, precedence only controls which operators are grouped with which operands - it does not control the order in which expressions are evaluated.
Second, the order in which function arguments are evaluated is unspecified - they can be evaluated right-to-left, left-to-right, or any other order1.
Finally, you are updating k (k = 50) and attempting to use it in a value computation (k == 35, k > 40) without an intervening sequence point, which is explicitly called out by the language definition as undefined behavior.
So the result can literally be anything, even what you expect it to be. You can’t rely on it to be consistent or predictable.
This is not the same as the order in which they are passed to the function.
printf("%d %d %d",k==35,k=50,k>40);
This is undefined behavior.
The order of evaluation of the arguments is simply unspecified.
See here and here for further explanation.
Order of evaluation of the operands of any C operator, including the order of evaluation of function arguments in a function-call expression, and the order of evaluation of the subexpressions within any expression is unspecified[...]. The compiler will evaluate them in any order, and may choose another order when the same expression is evaluated again.

Calling Convention Confusion [duplicate]

This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)
I'm not able to understand the output of this program (using gcc).
main()
{
int a=10;
printf("%d %d %d\n",++a, a++,a);
}
Output:
12 10 12
Also, please explain the order of evaluation of arguments of printf().
The compiler will evaluate printf's arguments in whatever order it happens to feel like at the time. It could be an optimization thing, but there's no guarantee: the order they are evaluated isn't specified by the standard, nor is it implementation defined. There's no way of knowing.
But what is specified by the standard, is that modifying the same variable twice in one operation is undefined behavior; ISO C++03, 5[expr]/4:
Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored. The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression; otherwise the behavior is undefined.
printf("%d %d %d\n",++a, a++,a); could do a number of things; work how you expected it, or work in ways you could never understand.
You shouldn't write code like this.
AFAIK there is no defined order of evaluation for the arguments of a function call, and the results might vary for each compiler. In this instance I can guess the middle argument was first evaluated, following by the first, and the third.
As haggai_e hinted, the parameters are evalueted in this order: middle, left, right.
To fully understand why these particular numbers are showing up, you have to understand how the increment works.
a++ means "do something with a, and then increment it afterwards".
++a means "increment a first, then do something with the new value".
In your particular Example, printf evaluates a++ first, reads 10 and prints it and only then increments it to 11. printf then evaluates ++a, increments it first, reads 12 and prints it out. The last variable printf evaluates is read as it is (12) and is printed without any change.
Although they are evaluated in a random order, they are displayed in the order you mentioned them. That's why you get 12 10 12 and not 10 12 12.

Unexpected working of printf() in C [duplicate]

This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 9 years ago.
#include<stdio.h>
int main()
{
int i=2;
printf("%d %d \n",++i,++i);
}
The above code gives an output 4 4. Can any one help how to explain the output?
++i is a prefix increment. Printf should first evaluate its arguments before printing them (although in which order, is not guaranteed and, strictly speaking, undefined - See Wiki entry on Undefined Behavior: http://en.wikipedia.org/wiki/Undefined_behavior ).
The prefix increment is called "increment and fetch", i.e. it first increments the value and then gives it to the caller.
In your case, i was first incremented twice, and only afterwards the output was formatted and sent to the console.
It has to do with sequence points and it can result in undefined behavior.
Straight from Wikipedia:
Before a function is entered in a function call. The order in which
the arguments are evaluated is not specified, but this sequence point
means that all of their side effects are complete before the function
is entered.
More info here: http://en.wikipedia.org/wiki/Sequence_point
Both the answers have made the same mistake. Its clear cut UB and not just unspecified behavior.
What you have experienced is Undefined behavior. Please read about sequence points. Comma is a separator in function calls not an operator.
A sequence point is a point in time at which the dust has settled and all side effects which have been seen so far are guaranteed to be complete. The sequence points listed in the C standard are:
at the end of the evaluation of a full expression (a full
expression is an expression statement, or any other expression which
is not a subexpression within any larger expression);
at the ||, &&, ?:, and comma operators; and
at a function call (after the evaluation of all the arguments, and just before the actual call).
The Standard states that
Between the previous and next sequence point an object shall have its
stored value modified at most once by the evaluation of an expression.
Furthermore, the prior value shall be accessed only to determine the
value to be stored.
What will be evaluated first this "%d %d \n", this ++i or this ++i (second one) - think about it. This would be unspecified behavior:
void f(int x)
{
printf("%d ",x);
}
int main()
{
int i=0;
f(i++) ;
}
From wiki:
Before a function is entered in a function call. The order in which
the arguments are evaluated is not specified, but this sequence point
means that all of their side effects are complete before the function
is entered. In the expression f(i++) + g(j++) + h(k++), f is called
with a parameter of the original value of i, but i is incremented
before entering the body of f. Similarly, j and k are updated before
entering g and h respectively. However, it is not specified in which
order f(), g(), h() are executed, nor in which order i, j, k are
incremented. Variables j and k in the body of f may or may not have
been already incremented. Note that a function call f(a,b,c) is not a
use of the comma operator and the order of evaluation for a, b, and c
is unspecified.

post increment and pointer in printf [duplicate]

This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 9 years ago.
Can someone please explain why this code is outputing 2 1, I thought post-increment was supposed to be applied after the printf instruction.
#include <stdio.h>
int main() {
int i=1;
int *p=&i;
printf("%d %d\n", *p ,i++);
return 0;
}
The order of evaluation of is not specified for this case in the standard and so you can not determine whether *p or i++ will be evaluated first. The C99 draft standard says in section 6.5.2.2 Function calls paragraph 10 says:
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.
This is also undefined behavior because you are modifying i and accessing the previous value of i in another expression within the same sequence point, the draft standard in section 6.5 Expressions paragraph 2 says:
Between the previous and next sequence point an object shall have its stored value
modified at most once by the evaluation of an expression.72) Furthermore, the prior value
shall be read only to determine the value to be stored
Comma is a sequence point, but not in function calls.
And printf is a function with arguments separated with commas.
In expression like this:
if(i+2,i++). . . comma is a sequence point and assures that expressions will be evaluated from left to right, and final value of expression will be value of rightmost sub-expression. In this case i++.
On the other hand in funcion call:
function(i+1,i++,i--) comma in not a sequence point and any of sub-expressions can be evaluated as first. The only thing sure is that they all be evaluated, but not in any specific order.

undefined behaviour in C [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicates:
Parameter evaluation order before a function calling in C
order of evaluation of function parameters
What will be the output of the following code:
n=5;
printf("%d %d\n", ++n, power(2, n));
output=32
shoulld not be the output be 2^6 =64?
will different compilers give different result?
Order of evaluation of function arguments is unspecified. The compiler can compute the arguments in any order it pleases, but it must do it in some particular order (so there's no undefined behaviour here). The output can be either 32 or 64.
UPD: this is wrong, there's UB here, see here.
Contrary to what other answers say, the code may indeed exhibit undefined behavior.
As has been stated, the order of evaluation of function arguments is unspecified in C. In your program, you have an expression composed of several subexpressions:
ex0(ex1, ex2, ex3(ex4, ex5));
There is only a partial ordering between these subexpressions: ex4 and ex5 must obviously be evaluated before ex3 can be evaluated, and ex1, ex2, and ex3 must be evaluated before ex0 can be evaluated. Other than that, the order of evaluation of the subexpressions is unspecified, and it is up to your compiler to decide the order in which to evaluate the subexpressions.
There are certain, valid orders of evaluations that yield undefined behavior. For example, if ++n is evaluated before power(2, n), the results are undefined: there is a sequence point after the evaluation of all of the arguments to a function but not before or between, and the C Language Standard very clearly states (C99 §6.5/2; emphasis mine):
Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.
If ++n is evaluated first, this rule is violated because n is modified by ++n and n is read for the call to power(2, n) without a sequence point between those two steps.
A program that exhibits undefined behavior may produce any result: it may crash, it may print an unexpected answer, or it may appear to work as you expect it to work. Since your program potentially exhibits undefined behavior, it's difficult to discuss with certainty the actual behavior that you see. It is best to avoid writing programs that potentially (or worse, actually) exhibit undefined behavior.
And what does your power function contain? I just checked C math libraries pow function. I had to cast it to <int> like this;
#include <cstdio>
#include <cmath>
using namespace std;
int main () {
int n=5;
printf("%d %d\n", ++n, (int)pow(2.0, n));
return 0;
}
Output: 6 64
I used Microsoft Compiler(used by Visual Studio). Hope it helps.

Resources