Code :
#include<stdio.h>
#include<stdlib.h>
int arr[] = {1, 2, 3, 4};
static int count = 0;
int incr( ) {
++count;
++count;
return count;
}
int main(void)
{
printf("\ncount= %d \n",count);
int i;
arr[count++]=incr( );
for(i=0;i<4;i++)
printf("arr[%d]=%d\n", i,arr[i]);
printf("\nIncremented count= %d \n",count);
return 0;
}
Output
count = 0
arr[0]=2
arr[1]=2
arr[2]=3
arr[3]=4
Incremented count = 1
The final incremented value of global variable count is 1 even though it has been incremented thrice.
When count++ is replaced by count in arr[count++]=incr( ) the final incremented value of count is 2.
This is undefined behaviour from bad sequencing. On this line:
arr[count++]=incr( );
What happens (with your compiler) is:
arr[count] is resolved to arr[0], postfix ++ will be applied at the end of the
statement;
incr() is called, count is now equal to 2, incr() returns 2;
arr[0] gets assigned 2;
postfix ++'s side effect kicks in, and count is now equal to 1. Previous changes to count are lost.
You will find more info on "side effects" and "sequence points" by googling their real name :)
To understand why your code goes wrong, you must first understand undefined behavior and sequence points, which is a rather advanced topic. You also need to understand what undefined behavior is, and what unspecified behavior is, explained here.
If you do something to a variable which counts as a side-effect, such as modifying it, then you are not allowed to access that variable again before the next sequence point, for other purposes than to calculate which value to store in your variable.
For example i = i++ is undefined behavior because there are two side effects on the same variable with no sequence point in between. But i = i+1; is well-defined, because there is only one side effect (the assignment) and the i+1 is only a read access to determine what value to store.
In your case, there is no sequence point between the arr[count++] sub-expression and the incr() sub-expression, so you get undefined behavior.
This is how sequence points appear in functions, C11 6.5.2.2:
There is a sequence point after the evaluations of the function
designator and the actual arguments but before the actual call. Every
evaluation in the calling function (including other function calls)
that is not otherwise specifically sequenced before or after the
execution of the body of the called function is indeterminately
sequenced with respect to the execution of the called function.
This means that the contents of the function aren't sequenced in relation to the rest of the expression. So you are essentially writing an expression identical to arr[count++] = ++count;, except through the function you managed to squeeze in two unsequenced ++count on the right side of the operation, which wouldn't otherwise be possible. Any any rate, it is undefined behavior.
Fix your code by enforcing sequence points between the left hand and the right hand of the expression. However, the order of evaluation of sub-expressions is unspecified behavior, so you need to ensure that your code is safe no matter if the left or right side is evaluated first. This code will fix the problems:
// artificial example, don't write code like this
0,arr[count++] = 0,incr();
since the comma operator introduces a sequence point. But of course, writing nonsense code like that isn't something you should be doing. The real solution is to never use ++ together with other operators in the same expression.
// good code, write code like this
arr[count] = incr();
count++;
Related
So, I understand that i++ increments post the condition is fulfilled, while ++i increments before the condition is fulfilled. That takes me to my question:
#include<stdio.h>
int main()
{
int i=0;
while(++i<10)
printf("%d\n",i);
return 0;
}
Now here we need the initialization of i from 0 as when it goes in the while loop, it will get incremented first, and thus it will be like while(1<10), and so it will print numbers from one to ten.
Second code:
#include<stdio.h>
int main()
{
int i=0;
while(i++<10)
printf("%d\n",i);
return 0;
}
Now since i++ increments after the value has been used, so why do we initialize i from i=0, as if it gets incremented after the comparision of value of i takes place, then why isn't 0 getting printed as well because the first loop should go like while(0<10), and not like while(1<10)? So, why is zero not getting printed?
Thank you for your time.
Yes, the first condition will evaluate to 0 < 10. You can verify that by changing it to while (i++ < 1) and see that the loop still runs (once), so clearly it's using 0 for the condition (1 < 1 would be false of course).
So why does it print 1? Because it doesn't print whichever value was used for the condition. It prints the current value of i. And the current value of i is 1 at that point because i was incremented right after it was used in the condition.
The difference of pre- and post- increment applies only to the value that the expression evaluates to.
After the evaluation of i++<10 is completed, the incrementation is also completed, and i has the value 1 in the first iteration.
printf("%d\n",i); is executed after the evaluation of i++<10, so i has the value 1 here in the first iteration.
Zero isn't printed because i is incremented right after the comparison, like this:
while(i<10) {
i += 1;
printf("%d\n",i);
}
The first sentence of your question is almost the answer:
i++ increments post the condition is fulfilled
It's incremented after the condition is checked, so i++ < 10 will increment i regardless of whether the condition ends up true or false.
The operation of ++ is not done before or after any “condition” it is in. It must be completed sometime in or around the full expression it is in. The answers that say i is updated “before” or “after” the ++i or i++ is evaluated are incorrect.
Prefix ++i does two separate things that may happen in any order:
It evaluates to the value of i after one is added.
It adds one to the stored value of i.
Postfix i++ does two separate things that may happen in any order:
It evaluates to the value of i before one is added.
It adds one to the stored value of i.
That change to the stored value of i is called a side effect. It is disconnected from the main evaluation of the expression. It can be performed before, during, or after the evaluation of i, but the evaluation still returns the pre- or post-increment value, as described above.
A full expression is one that is not contained inside another expression. So, in while (++i < 10), ++i < 10 is a full expression. The side effect can occur before any part of that is evaluated, after the value of i plus one is calculated, or after the < is evaluated. It can also occur in parts (such as updating the bytes of i one by one) during the evaluations. However, the side effect must occur after any previous full expression and before any later full expression. That is because the C standard says there is a sequence point between any two full expressions. (And there are some other rules about order of execution.)
Even if the stored value of i is updated before i++ or after ++i, the expression must still produce the value of i before or after the increment, respectively. For example, for i++, the compiler can fetch i, add one, store i, but then use the pre-add value in the expression.
The result of i++ is the value of i. As a side effect i is incremented.
The result of ++i is the value of i + 1. As a side effect i is incremented.
The statement
x = i++;
is logically equivalent to
tmp = i;
x = tmp;
i = i + 1;
with the caveat that the assignments to x and i can happen in any order, or even simultaneously (interleaved or in parallel).
Similarly, the statement
x = ++i;
is logically equivalent to
tmp = i + 1;
x = tmp;
i = i + 1;
with the same caveat as above. Again, these are logical equivalents, not what the compiler actually generates - depending on the compiler and the code involved there may not be a temporary.
In the second code, the increment will take place after the condition but before the printing statement.
Thus, the incremented value of i is printed.
This is your answer in simple language.
can someone explain why this prints out : "d ce"
I think i understood why it prints out "d" but i don't understand the "ce"
#include <stdio.h>
int main(void){
char s1[]="abcd",*cp;
cp=s1+2;
printf("%c %s\n",(*(++cp))++,s1+2);
return 0;
}
TL;DR
In order to understand this code, you need rather in-depth C knowledge of sequence points, undefined behavior and misc "language-lawyer" stuff. If that isn't the case, then just simply forget about writing or understanding artificial crap code like this and you can stop reading here. Advanced explanation follows.
C11 6.5 states:
If a side effect on a scalar object is unsequenced relative to either a different side effect
on the same scalar object or a value computation using the value of the same scalar
object, the behavior is undefined. If there are multiple allowable orderings of the
subexpressions of an expression, the behavior is undefined if such an unsequenced side
effect occurs in any of the orderings.
Generally this renders weird code like this undefined behavior. But in this case, 1) s is not a scalar but an aggregate. The scalar is rather the s[3] lvalue. And 2) the )++ increment that changes the value is not unsequenced to another value computation using the object inside the same expression.
(*(++cp))++ and s1+2 are unsequenced in relation to each other but that doesn't matter for the purpose of making a case for undefined behavior.
cp=s1+2; here cp is pointing at the 'c'.
This expression alone (*(++cp))++ first increases the pointer one step to point at s[3] that contains 'd'. Then it dereferences the pointer so that we get the value 'd'.
It then increments the value by 1 with the postfix ++, which on most symbol tables means 'e'.
The ++ change of the value is not sequenced in relation to the value computation that happens during s1+2 but it doesn't matter.
All arguments are evaluated before the function is called and there is a sequence point after the full evaluation of the argument list.
printf then spots %s and de-references the string, a value computation, but sequenced in relation to the previous )++. This prints ce.
And finally there is another sequence point before the function returns.
So the code is actually well-defined, even though horribly written.
Hope the inline comments makes it clear.
#include <stdio.h>
int main()
{
char s1[]="abcd",s2[]="cdef",s3[5],*cp;
printf("s1 = %p\n", (void*)s1); // prints start address of s1
cp = s1+2; // cp points to 2 chars advanced of s1 i.e 'c'
printf("cp = %p\n", (void*)cp); // prints address at 'c'
//first increment cp to point to next location, which now points at 'd' from 'c'
//the outer ++ increments 'd' to 'e' post-fix, so first prints 'd'
printf("(*(++cp))++ = %c\n", (*(++cp))++);
printf("s1 = %s\n", s1); // you will see "abce"
printf("s1+2 = %s\n", s1+2); // 2 chars advanced of s1, i.e "ce"
//printf("%c %s\n",(*(++cp))++,s1+2);
return 0;
}
Why This code fail in first If statement?
My prediction getting wrong as per associations and precedence.
#include<stdio.h>
void main()
{
int i=10;
if(i==i--)
{
printf("In 1:%d\n",i);
printf("TRUE 1\n");
}
i=10;
if(i==--i)
{
printf("In 2:%d\n",i);
printf("TRUE 2\n");
}
}
i==i-- is undefined behaviour. Please check this: http://c-faq.com/expr/ieqiplusplus.html and this: http://c-faq.com/expr/seqpoints.html
The expression i==i-- will cause undefined behavior because there is no sequence point between the two evaluations of i and i--. This means that anything can happen and at that point the program no longer produces meaningful output.
The same is true for the expression i==--i
If an object is read and also modified without a sequence point separating the two events the behavior is undefined1. In this case the same object is modified (side effect): i-- and read (value computation): i, without a sequence point.
Correct code would separate the two expressions with a sequence point (character ;):
const int i1 = i;
const int i2 = i--;
if( i1 == i2 )
{
//...
}
const int i3 = i;
const int i4 = --i;
if( i3 == i4 )
{
//...
}
1 (Quoted from ISO/IEC 9899:201x 6.5 Expressions 2):
If a side effect on a scalar object is unsequenced relative to either a different side effect
on the same scalar object or a value computation using the value of the same scalar
object, the behavior is undefined.
Undefined behaviour because post and pre increment depend on compiler. Please see stack overflow question here.
C99 standard - 6.5 Expressions, §2
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.
There would be no compilation error. It does not go inside the first if statement as it is undefined behavior (as user babon mentioned).
The behavior actually depends on the compiler you're using.
I did not quite get your question. Are you asking "why does statements in only first if gets executed"? If yes, following is the reason
i-- evaluates the expression and then decrements
--i decrements first and then evaluate expression. So, second condition evaluates to 'false' (10 == 9)
I'm just learning some C, or rather, getting a sense of some of the arcane details. And I was using VTC advanced C programming in which I found that the sequence points are :
Semicolon
Comma
Logical OR / AND
Ternary operator
Function calls (Any expression used as an argument to a function call is finalized the call is made)
are all these correct ?. Regarding the last one I tried:
void foo (int bar) { printf("I received %d\n", bar); }
int main(void)
{
int i = 0;
foo(i++);
return 0;
}
And it didnt print 1, which according to what the VTC's guy said and if I undertood correctly, it should, right ?. Also, are these parens in the function call the same as the grouping parens ? (I mean, their precedence). Maybe it is because parens have higher precedence than ++ but I've also tried foo((i++)); and got the same result. Only doing foo(i = i + 1); yielded 1.
Thank you in advance. Please consider that I'm from South America so if I wasnt clear or nothing makes sense please, oh please, tell me.
Warmest regards,
Sebastian.
Your code is working like it should and it has nothing to do with sequence points. The point is that the postfix ++ operator returns the non-incremented value (but increments the variable by 1 nonetheless).
Basically:
i++ – Increment i by one and return the previous value
++i – Increment i by one and return the value after the increment
The position of the operator gives a slight hint for its semantics.
Sequence means i++ is evaluted before foo is invoked.
Consider this case (I am not printing bar!):
int i = 0;
void foo (int bar) { printf("i = %d\n", i); }
int main(void){
foo(i++);
return 0;
}
i = 1 must be printed.
C implements pass-by-value semantics. First i ++ is evaluated, and the value is kept, then i is modified (this may happen any time between the evaluation and the next sequence point), then the function is entered with the backup value as the argument.
The value passed into a function is always the same as the one you would see if using the argument expression in any other way. Other behavior would be fairly surprising, and make it difficult to refactor common subexpressions into functions.
When you do something like:
int i = 0, j;
j = i++;
the value of i is used first and then incremented. hence in your case the values of i which is 0 is used (hence passed to your function foo) and then incremented. the incremented values of i (now 1) will be available only for main as it is its local variable.
If you want to print 1 the do call foo this way:
foo(++i);
this will print 1. Rest you know, why!
From past few days I was trying to learn about undefined behavior. Few days ago I found a c-faq link. This helps a lot to clear many confusions, but creates an another big confusion when I read the question #3.8. After my lots of efforts to understand the statement (specially second sentence);
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.
I felt better to ask this question on SO but none of the answer there explained the second sentence of this statement. Finally, I got an explanation there about this point . After reading it and FAQ many times I concluded that;
1.The last sentence
Furthermore, the prior value shall be accessed only to determine the value to be stored
would be like this;
Furthermore, the prior value of an object shall be accessed only to determine the modified/new value( of same object ) to be stored.
As it is clear by the example
int i = 1, j, a[5];
i = i + 1;
j = i + 1;
a[i] = i;
in case of expression i = i + 1 prior value (which is 1 here) of i (in R.H.S) is accessed to determine the value of i to be stored. While in case of j = i + 1 and a[i] = i, the accessed value of i is just value not prior value as no where i is modified in these statements.
2.In case of expression a[i] = i++ or a[i++] = i, first sentence of above statement
Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression.
get failed as i is modified only once between two consecutive sequence point. And that's why we need second sentence.
Both of these examples are disallowed in C because the prior value of i accessed two times i.e, i++ itself access prior value of i in the expression to modify it and hence other access of prior value / value of i is needless as it is not accessed to determine the modified value to be stored.
The problem starts when I came up with the expression i = i++ about which it is stated in c-faq
Actually, the other expressions we've been discussing are in violation of the second sentence, as well.
I think in this expression i (in R.H.S) is accessed to determine the modified value of i.
How this expression is violating the second statement?
Think about it this way:
a = i++;
is equivalent to:
a = i;
i++;
The accesses the value of i in the increment has nothing to do with determining what value a will be stored into a. So i = i++ contains two modifications of i (which is disallowed by the first sentence), but also, the i = modification to i is independent from one of the accesses to i in i++.
I think someone was just being extra clever there. There's no need to figure how much an undefined behavior is undefined. Modifying a value twice is enough undefined.