Array subscription execution order [duplicate] - c

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.

Related

Order of evaluation of subexpressions [duplicate]

This question already has answers here:
Is the behaviour of i = i++ really undefined?
(9 answers)
Closed 8 years ago.
If the order of evaluation of sub expressions is not guaranteed, then why is this correct?
int a = 1;
a = a + 1;
Here the compiler could evaluate first a and then a + 1 so a can be 1 or 2
while this is not:
a = a++;
Here the compiler could evaluate first a and then a++ son a can be 1 or 2.
What's the difference?
It is undefined behavior. The reason follows::
The Standard in §5/4 says
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.
and
The prior value shall be accessed only to determine the value to be
stored.
It means, that between two sequence points a variable must not be modified more than once and, if an object is written to within a full expression, any and all accesses to it within the same expression must be directly involved in the computation of the value to be written.
Read about sequence points here , basically you have 2 assignments between 2 sequence points and that will cause undefined behavior.
a++ will increment value for a and then assign it to a and another assignment will be done by = operator, while a + 1 will not change value for a and you will have only 1 assignment between 2 sequence points

Why compiler treats i+++++i and i+++i differently [duplicate]

This question already has answers here:
Why doesn't a+++++b work?
(9 answers)
Closed 9 years ago.
int i=5;
printf("%d",i+++++i);
This gives error, but:
printf("%d",i+++i);
gives the output 11. In this case, the compiler read it as:
printf("%d",i+ ++i);
Why is this not done in first expression? i.e :
printf("%d",i+++++i);
Because of operator precedence i++++++i is treated as (i++)++ + i). This gives a compiler error because (i++) is not an lvalue.
Modifying the same variable multiple times between two sequence points is an Undefined Behavior according to §6.5 of language specifications
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.(71)
71) This paragraph renders undefined statement expressions such as
i = ++i + 1;
a[i++] = i;
while allowing
i = i + 1;
a[i] = i;
i+++++i is parsed as i ++ ++ + i. It contains an invalid subexpression i ++ ++. Speaking formally, this expression contains a constraint violation, which is why it does not compile.
Meanwhile i+++i is parsed as i ++ + i (not as i + ++ i as you incorrectly believe). It does not contain any constraint violations. It produces undefined behavior, but is otherwise well-formed.
Also, it is rather naive to believe that printf("%d",i+++i) will print 11. The behavior of i+++i is undefined, meaning that there's no point in trying to predict the output.
In printf("%d",i+++++i);, the source text i+++++i is first processed according to this rule from C 2011 (N1570) 6.4 4:
If the input stream has been parsed into preprocessing tokens up to a given character, the next preprocessing token is the longest sequence of characters that could constitute a preprocessing token…
This causes the lexical analysis to proceed in this way:
i can be a token, but i+ cannot, so i is the next token. This leaves +++++i.
+ and ++ can each be a token, but +++ cannot. Since ++ is the longest sequence that could be a token, it is the next token. This leaves +++i.
For the same reason, ++ is the next token. This leaves +i.
+ can be a token, but +i cannot, so + is the next token. This leaves i.
i can be a token, but i) cannot, so i is the next token.
Thus, the expression is i ++ ++ + i.
Then the grammar rules structure this expression as ((i ++) ++) + i.
When i++ is evaluated, the result is just a value, not an lvalue. Since ++ cannot be applied to a value that is not an lvalue, (i ++) ++ is not allowed.
After the compiler recognizes that the expression is semantically incorrect, it cannot go back and change the lexical analysis. Th C standard specifies that the rules must be followed as described above.
In i+++i, the code violates a separate rule. This is parsed as (i ++) + i. This expression both modifies i (in i ++) and separately accesses it (in the i of + i). This violates C 2011 (1570) 6.5 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.
This rule uses some technical terms: In i ++, the effect of changing i is a side effect of ++. (The main effect is to produce the value of i.) The use of i in + i is a value computation of the scalar object i. And these two things are unsequenced, because the C standard does not specify whether producing the value of i for + i comes before or after changing i in i ++.

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.

post increment,pre increment and operator precedence [duplicate]

This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 9 years ago.
the answer is coming out to be 45.I cant understand how this thing is working.
main()
{
int a =10;
int i = a++ + ++a + a++ + ++a;
printf("%d , %d ", i,a);
}
Actually the output is an undefined behavior which is fine.
From the C99 standard are 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.
The order of evaluation of the operands is unspecified. If an attempt
is made to modify the result of an assignment operator or to access it
after the next sequence point, the behavior is undefined.

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