How exactly is the program running? - c

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.

Related

Operator Precedence in C language

Can someone tell me what is happening behind the scenes here?
main()
{
int z, x=5, y=-10, a=4, b=2;
z = ++x - --y*b/a;
printf("%d", z);
}
Strange way to write code man...anyway...I try...
Resolves ++x and --y
Resolves multiplications and divisions
Resolves the remaining (plus and minus)
So...
z= 6 - (-11) * 2 /4
z= 6 - (-22) / 4
z= 6 - (-5) (the result is truncated due to (-22) / 4 being an integer division)
I get z= 11.
The variable z is declared int so it becomes 11.
I suggest to write this line in a simpler way!! Oh...sorry for my english...
This expression
z=++x - --y*b/a;
is evaluated in the following order in an abstract machine
Variable x is incremented and becomes equal to 6.
Variable y is decremented and becomes equal to -11.
Variable y is multiplied by variable b and the result is equal to -22.
The result of the preceding operation is divided by variable a and as there is used the integer arithmetic the result is equal to -5.
At last there is subtraction of the result from variable x and the result is equal to 11.
Run the program and be sure whether I am correct.
Take into account that a particular implementation may evaluate the operands in a different order provided that the result will be the same as I described for the abstract machine.
According to the C Standard (5.1.2.3 Program execution)
4 In the abstract machine, all expressions are evaluated as specified
by the semantics. An actual implementation need not evaluate part of
an expression if it can deduce that its value is not used and that no
needed side effects are produced (including any caused by calling a
function or accessing a volatile object).
First of all, please note the difference between operator precedence and order of evaluation of sub expressions.
Operator precedence dictates which operations that have to be done and evaluated, before the result of those operations are used together with the rest of the expression. This works similarly to mathematical precedence: 1 + 1 * 2 is guaranteed to give result 3, not 4. Because * has higher precedence than +.
Order of evaluation equals the actual order of execution, and is unspecified behavior, meaning that a compiler is free to execute the various sub expressions in any order it likes, in order to produce the fastest possible code. And we can't know the order. Most operators in C involve unspecified order of evaluation (except some special cases like && || ?: ,).
For example the in the case of x = y() + z(), we can know that + operation will get executed before =, but we can't tell which of the functions y and z that will get executed first. It may or may not matter to the result, depending on what the functions do.
Then to the expression in the question:
Operator precedence dictates that the two operations ++x and --y must be evaluated before the other operations, since the prefix unary operators have highest precedence of those present in the expression.
Which sub expression of ++x and --y*b/a that is evaluated first is not specified. We can't tell the order of execution (and --y*b/a does in turn contain several sub expressions). At any rate, the order of evaluation does not matter here, it will not affect the result.
The increments/decrements ++x and --y will take place before the results of those operations are used together with the rest of the expression.
Operator precedence then dictates that the operations involving * and / must be evaluated next. These operators have the same precedence, but they belong to the multiplicative operators group, which has left-to-right associativity, meaning that --y*b/a is guaranteed to evaluate --y*b first. After that, the result will get divided by a.
So the whole right-most sub expression is equivalent to ( (--y) * b ) / a.
Next, operator precedence dictates that - has higher precedence than =. So the result of the sub expressions ++x is subtracted by the result of the sub expression --y*b/a .
And finally the result is assigned to z, since = had the lowest precedence.
EDIT
Btw, the proper way to write the same, and get the very same machine code, is this:
++x;
--y;
z = x - (y*b)/a;
Apart from giving reduced readability, the ++ and -- operators are dangerous to mix with other operators since they contain a side effect. Having more than one side effect per expression could easily lead to various forms of unsequenced processing, which is always a bug, possibly severe. See this for examples.
"Operator precedence" means the rules for deciding what the operands are of each operator. In your case, using parentheses to indicate:
z=++x - --y*b/a;
is equivalent to:
z = ((++x) - (((--y) * b) / a));
Now, this line of code and the following printf statement has the same observable behaviour as the code:
z = (x + 1) - ((y - 1) * b / a);
printf("%d\n", z);
x = x + 1;
y = y - 1;
C is defined in terms of observable behaviour (which approximately means the output generated by the program; you can see a technical definition by reading the C standard). Any two programs which would produce the same observable behaviour according to the standard , are considered to be exactly equivalent.
This is sometimes called the "as-if rule" and it is this rule that allows optimization to occur.
Addressing points raised by some of the other answers:
There are rules surrounding exactly what ++ and -- do. Specifically, the effects of incremeting x and decrementing y are defined so that the writing back of the increment and decrement could happen at any time during the execution of z=++x - --y*b/a; . They could be in either order, or simultaneous; the writing of the decrement could be either before or after the computation of (y-1) * b, and so on.
In some different code examples, we would use these rules to work out the observable behaviour of the program, and it would not be quite so flexible as this particular program.
But in this code example, since nothing else depends on the timing of those increments and decrements, it turns out that we can even hoist them past the printf, according to the "as-if rule".

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.

Pre-increment operation in C

I'm just starting a beginner's guide to games programming tutorial in C. I'm a little confused with the code below.
At main gameOverTick is set to zero, then we have a case when the game is over
case GAME_OVER:
printStatus("GAME OVER!!! The evil DarkLord was defeated");
if (++gameOverTick % 100 == 0){
status = PRINT_GAME_WELCOMESCREEN; // go back to welcome screen
gameOverTick = 0; // reset gameOverTick
}
I would just like to know what role the ++ (pre-inc) operation does on gameOverTick. Does it set gameOverTick to 1 whilst checking the if, or set it to 0 somehow. I know how post-inc ++ works, but this is a new one for me.
Thanks
We've got four answers here and they are all wrong in the same way. Let me make sure this is very clear in your mind: people who tell you that precedence of operators determines the order in which side effects occur as a result of computation of subexpressions are simply wrong. In C, the order in which subexpressions are computed is not controlled by precedence; it is largely undefined. (In C# and Java is is defined not as precedence order but as left-to-right.)
In the specific case here, the value of the ++ operation must be computed before the % happens, but the assignment associated with the ++ operation can happen at any time. In your particular case it doesn't matter when the assignment happens, but it is easy to construct cases where it does matter.
This increases gameOverTick by one before the modulo is calculated and the comparison is done. (A good rule of thumb in C is that unitary operations have tighter binding than binary, and calculations over logic operations.) It guess the purpose of this is to wait 100 loops until it goes hack to the welcome screen, as gameOverTick is only reset if it have gone up to 100.
Most expressions in C have a value; most expressions have a side effect.
Consider the two expressions below
/* a */ i++
/* b */ ++i
The side effect of both expressions is to increase the value of i (that change is only usable after the next sequence point). The value of the first expression is the value i had on the previous sequence point; the value of the second expression is one more than what i had at the previous sequence point.
The code you have written inside parenthesis of if is called an expression, the expression evaluation always follow operator precedence rule, considering the given expression
1.++ operator has highest precedence so '++gameOverTick' is evaluated first as '(gameOverTick = gameOverTick+1)'
2.The next next precedence is for '%' operator so '(gameOverTick+1)%100' is calculated
3.Finally the least precedence operator is '==' hence the obtained result on left side of '==' operator is compared for equality with the right side value.
Example:
-Consider gameOverTick value as 99
-99 is incremented first i.e, 99+1 = 100
-Than the % operation is performed i.e, 100%100 = 0
-Now equality is compared` i.e, 0 == 0 which gives 1
-The evaluation of expression gives 1 hence it is equal to if(1), which indicates a true.
For more on operator precedence you can refer this link
http://www.difranco.net/compsci/C_Operator_Precedence_Table.htm

Is it safe to use foo() && 0 in C?

Imagine i have the following piece of C-code where foo() produces a side effect and returns an integer:
if(bar) {
foo();
return 0;
}
Now, say I really like making my code compact, possibly at the reader's expense, and I change it into this:
if (bar)
return foo() && 0;
Can I be sure these two pieces of code will produce the same behavior, or would I risk the call to foo() not being executed due to possible compiler optimizations or something like that, thus not producing the desired side-effect?
NOTE: This is not a question about which piece of code is better, but whether the two pieces actually produce the same behavior in all cases. I think the majority (and I) can agree that the former piece of code should be used.
Yes, those two are the same. foo() will always be called (assuming bar is true).
The two forms you give are equivalent. The C11 standard (draft n1570) states,
6.5.13 Logical AND operator
...
Semantics
3 The && operator shall yield 1 if both of its operands compare unequal to 0;
otherwise, it yields 0. The result has type int.
4 Unlike the bitwise binary & operator, the && operator guarantees left-to-right
evaluation; if the second operand is evaluated, there is a sequence point between
the evaluations of the first and second operands. If the first operand compares
equal to 0, the second operand is not evaluated.
Similar language appeared in all C standards so far.
You should probably prefer using the comma operator here (return foo(), 0;) because:
It's shorter (one character versus two for the operator, and you can get away with removing the left space character when using a comma, for a total of two fewer characters).
It gives you more flexibility, as you can return non-scalar types (such as structs), and a wider range of integers than just 0 or 1.
It conveys the intent better: "Discard return value of foo() and return something else (0) instead".
Now if you do chance upon a compiler that deletes the call to foo(), then either the compiler managed to prove that foo() is a function with no visible side-effects, or more likely it has a serious bug and you should report it.
Why obfuscate your code in the latter?
Use the former.
Easier to read i.e. this is easier to understand
if(bar) {
foo();
return 0;
}
Or unless got a problem with job security

with conditional ?: expression, at what point do postfix operations occur?

For example, the difference between these two statements:
if ( ucNum++ >= 3 ) // ucNum incremented after comparing its value to 3, correct?
{
ucNum = 0;
}
vs.
ucNum++ >= 3 ? ucNum = 0 : 1; // does incrementing it happen somewhere in the middle of the inline?
Perhaps it is compiler specific. Where should it occur in the conditional expression?
The rules are that the condition is evaluated before choosing which alternative to evaluate. Since part of the evaluation is the ++, the increment will occur before the assignment (if the assignment occurs at all).
As #caf comments, there is a sequence point after the controlling expression. So, while (as David Thornley points out) the order of expression evaluations can be rearranged by the compiler (particularly side effect evaluations), the rearranging cannot cross sequence points.
Well, I've tested this practically (good thing printf returns int) with:
int ucNum = 4;
ucNum++ >= 3 ? printf("%d", ucNum) : 1;
Since the condition is true, it goes to the printf which prints 5. So definitely ucNum is incremented between the evaluation of the condition and the choosing of the return value.
You're looking for 6.5.15/4 in the C Standard. The first expression is completely evaluated, including side effects, before the selected one of the other two. This is not compiler-dependent, except in the sense that some compilers may be broken.

Resources