post increment and pointer in printf [duplicate] - c

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.

Related

Why does the value of i not increment for i=i++; statement? [duplicate]

This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 2 years ago.
Code:
for(int i=0;i<5;){
i=i++;
printf("%d",i);
}
The above program print zeros infinitely, How is that possible?
There is the statement i=i++;. Please explain why the value of i do not increment.
The statement i = i++ is undefined behaviour in C. Simplistically, modifying and using the same object without an intervening sequence point is not guaranteed to work in any way you expect.
Sequence points are covered in Appendix C of the ISO C standard if you're interested in an in-depth investigation. Basically, they consist of:
Between the evaluations of the function designator and actual arguments in a function call and the actual call.
Between the evaluations of the first and second operands of the following operators: logical AND &&; logical OR ||; comma ,.
Between the evaluations of the first operand of the conditional ?: operator and whichever of the second and third operands is evaluated.
The end of a full declarator.
Between the evaluation of a full expression and the next full expression to be evaluated. The following are full expressions: an initializer that is not part of a compound literal; the expression in an expression statement; the controlling expression of a selection statement (if or switch); the controlling expression of a while or do statement; each of the (optional)
expressions of a for statement; the (optional) expression in a return
statement.
Immediately before a library function returns.
After the actions associated with each formatted input/output function conversion specifier.
Immediately before and immediately after each call to a comparison function, and also between any call to a comparison function and any movement of the objects passed as arguments to that call.

printf() function evaluation of pre and post decrements in C [duplicate]

This question already has answers here:
Parameter evaluation order before a function calling in C
(7 answers)
Undefined behavior and sequence points
(5 answers)
Closed 8 years ago.
#include<stdio.h>
int main()
{
int i = 2;
printf("\n %d %d %d \n",--i,i--,i); // 0 2 2
return 0;
}
The output prints 0 2 0 and not 0 2 2.I couldn't understand, as I assumed that the printf() evaluates from right to left.
Your code exhibits Unspecified behaviour. As per c99 standard document, chapter 6.5.2.2, paragraph 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.
Again, this shows undefined behaviour, because, i is getting modified more than once between two sequence points. As per chapter 6.5 paragraph 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.
printf evaluates nothing. It is the compiler that evaluates arguments of a function (that is it is the compiler that generates the object code) and the order in which the arguments will be evaluated in C is unspecified. So the compiler may evaluates them in any order.

Array subscription execution order [duplicate]

This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 8 years ago.
How this code fragment work for array subscription execution direction.
Please explain.
static int a[][2][3]={0,1,2,3,4,5,6,7,8,9,10,11,12};
int i=-1;
int d;
d=a[i++][++i][++i];
printf("%d",d);
This invokes undefined behaviour. Quoting C99 standard §6.5 ¶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 is no sequence point in the evaluation of the array index in
d = a[i++][++i][++i];
Therefore, it's not known when the side effects of evaluation of expressions in [] will take place. Quoting C99 stanadard again §6.5.2.1 ¶2
The definition of the subscript operator [] is that E1[E2] is
identical to (*((E1)+(E2))).
Therefore, the expression a[i++][++i][++i] evaluates to
a[i++][++i][++i]
== *((a[i++][++i]) + (++i))
== *(*((a[i++]) + (++i)) + (++i))
== *(*(*(a + i++) + (++i)) + (++i))
Adding parentheses does not create a sequence point. It only defines the order of evaluation of sub-expressions of the complete expressions. It does not guarantee when the side effects of evaluating the sub-expression will take place.
a[i++][++i][++i]
This statement results in undefined behaviour.
you can try executing code here and you will get different output than 2 that you got. Its not that you will not get output but the behaviour is undefined so you cant predict the output.

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.

Why doesn’t this code: a[i] = i++; work? [duplicate]

This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 9 years ago.
a[i] = i++;
Why does the above code not work?
What is wrong with above code? I am asking this question to improve my knowledge.
Because the ISO standard says that you are not allowed to change a variable more than once (or change and use one) without an intervening sequence point.
There is no sequence point between the use of i in a[i] and the change of i in i++.
The list of sequence points from C11 (not really changed that much since C99) are described in Annex C:
Between the evaluations of the function designator and actual arguments in a function call and the actual call.
Between the evaluations of the first and second operands of the following operators: logical AND &&; logical OR ||; comma ,.
Between the evaluations of the first operand of the conditional ?: operator and whichever of the second and third operands is evaluated.
The end of a full declarator: declarators;
Between the evaluation of a full expression and the next full expression to be evaluated. The following are full expressions: an initializer; the expression in an expression statement; the controlling expression of a selection statement (if or switch); the controlling expression of a while or do statement; each of the expressions of a for statement; the expression in a return statement.
Immediately before a library function returns.
After the actions associated with each formatted input/output function conversion specifier.
Immediately before and immediately after each call to a comparison function, and also between any call to a comparison function and any movement of the objects passed as arguments to that call.
and 5.1.2.3 Program execution states:
Evaluations A and B are indeterminately sequenced when A is sequenced either before or after B, but it is unspecified which.
The presence of a sequence point between the evaluation of expressions A and B implies that every value computation and side effect associated with A is sequenced before every value computation and side effect associated with B.
Section 6.5 Expressions pretty much covers your exact case:
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.
This paragraph renders undefined statement expressions such as i = ++i + 1; and a[i++] = i; while allowing i = i + 1; and a[i] = i;.
It does work, but possibly not as expected. The problem is if it's not clear if i gets incremented before the assignment and, if so, then a[i] will reference the next item in the array.
Your question was very terse so you can expand on it if you want more information. But it's just hard to tell exactly which element of a that syntax assigns to.

Resources