array manipulation results - c

can someone provide me more insight on why this code works the way it works
#include <stdio.h>
int main()
{
int a[5] = {1,2,3,4,5};
int i;
for(i=0;i<5;i++)
{
printf("%d,%d \n",i[a],i[a]++);
}
return 0;
}
The result is
2,1
3,2
4,3
5,4
6,5
Thanks

The behavior is undefined.
N1256 6.5p2:
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 program both modifies i[a] (in i[a]++) and reads its value (in the next argument), and the result of reading the value is not used to determine the value to be stored.
This is not just a matter of the unspecified order of evaluation of function arguments; the fact that there's no sequence point between i[a]++ and i[a] (since that's not a comma operator) means that the behavior, not just the result, is undefined.

It works by undefined behaviour. The order of evaluation of function arguments is not defined. The comma is not a sequence point.
EDIT: ooops, I read to fast. There is only one write to the a[i] object, so the behaviour is not undefined, only the results.

"i[a]++" is a post increment, so it will return the value of i[a] and then increment i[a] right away.
In your case, the third parameter of printf gets evaluated before the second (the evaluation order of function parameters is unspecified as far as I know), and thus the second parameter returns the already incremented value.

Related

issue with assignment operator inside printf()

Here is the code
int main()
{
int x=15;
printf("%d %d %d %d",x=1,x<20,x*1,x>10);
return 0;
}
And output is 1 1 1 1
I was expecting 1 1 15 1 as output,
x*1 equals to 15 but here x*1 is 1 , Why ?
Using assignment operator or modifying value inside printf() results in undefined behaviour?
Your code produces undefined behavior. Function argument evaluations are not sequenced relative to each other. Which means that modifying access to x in x=1 is not sequenced with relation to other accesses, like the one in x*1. The behavior is undefined.
Once again, it is undefined not because you "used assignment operator or modifying value inside printf()", but because you made a modifying access to variable that was not sequenced with relation to other accesses to the same variable. This code
(x = 1) + x * 1
also has undefined behavior for the very same reason, even though there's no printf in it. Meanwhile, this code
int x, y;
printf("%d %d", x = 1, y = 5);
is perfectly fine, even though it "uses assignment operator or modifying value inside printf()".
Within a function call, the function parameters may be evaluated in any order.
Since one of the parameters modifies x and the others access it, the results are undefined.
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.
It doesn't impose an order of evaluation on sub-expressions unless there's a sequence point between them, and rather than requiring some unspecified order of evaluation, it says that modifying an object twice produces undefined behaviour.

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.

Defined behaviour for expressions

The C99 Standard says in $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.
(emphasis by me)
It goes on to note, that the following example is valid (which seems obvious at first)
a[i] = i;
While it does not explicitly state what a and i are.
Although I believe it does not, I'd like to know whether this example covers the following case:
int i = 0, *a = &i;
a[i] = i;
This will not change the value of i, but access the value of i to determine the address where to put the value. Or is it irrelevant that we assign a value to i which is already stored in i? Please shed some light.
Bonus question; What about a[i]++ or a[i] = 1?
The first sentence:
Between the previous and next sequence point an object shall have its
stored value modified at most once by the evaluation of an expression.
is clear enough. The language doesn't impose an order of evaluation on subexpressions unless there's a sequence point between them, and rather than requiring some unspecified order of evaluation, it says that modifying an object twice produces undefined behavior. This allows aggressive optimization while still making it possible to write code that follows the rules.
The next sentence:
Furthermore, the prior value shall be read only to determine the value to be stored
does seem unintuitive at first (and second) glance; why should the purpose for which a value is read affect whether an expression has defined behavior?
But what it reflects is that if a subexpression B depends on the result of a subexpression A, then A must be evaluated before B can be evaluated. The C90 and C99 standards do not state this explicitly.
A clearer violation of that sentence, given in an example in the footnote, is:
a[i++] = i; /* undefined behavior */
Assuming that a is a declared array object and i is a declared integer object (no pointer or macro trickery), no object is modified more than once, so it doesn't violate the first sentence. But the evaluation of i++ on the LHS determines which object is to be modified, and the evaluation of i on the RHS determines the value to be stored in that object -- and the relative order of the read operation on the RHS and the write operation on the LHS is not defined. Again, the language could have required the subexpressions to be evaluated in some unspecified order, but instead it left the entire behavior undefined, to permit more aggressive optimization.
In your example:
int i = 0, *a = &i;
a[i] = i; /* undefined behavior (I think) */
the previous value of i is read both to determine the value to be stored and to determine which object it's going to be stored in. Since a[i] refers to i (but only because i==0), modifying the value of i would change the object to which the lvalue a[i] refers. It happens in this case that the value stored in i is the same as the value that was already stored there (0), but the standard doesn't make an exception for stores that happen to store the same value. I believe the behavior is undefined. (Of course the example in the standard wasn't intended to cover this case; it implicitly assumes that a is a declared array object unrelated to i.)
As for the example that the standard says is allowed:
int a[10], i = 0; /* implicit, not stated in standard */
a[i] = i;
one could interpret the standard to say that it's undefined. But I think that the second sentence, referring to "the prior value", applies only to the value of an object that's modified by the expression. i is never modified by the expression, so there's no conflict. The value of i is used both to determine the object to be modified by the assignment, and the value to be stored there, but that's ok, since the value of i itself never changes. The value of i isn't "the prior value", it's just the value.
The C11 standard has a new model for this kind of expression evaluation -- or rather, it expresses the same model in different words. Rather than "sequence points", it talks about side effects being sequenced before or after each other, or unsequenced relative to each other. It makes explicit the idea that if a subexpression B depends on the result of a subexpression A, then A must be evaluated before B can be evaluated.
In the N1570 draft, section 6.5 says:
1 An expression is a sequence of operators and operands that
specifies computation of a value, or that designates an object
or a function, or that generates side effects, or that performs
a combination thereof. The value computations of the operands
of an operator are sequenced before the value computation of the
result of the operator.
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. 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.
3 The grouping of operators and operands is indicated by the syntax.
Except as specified later, side effects and value computations
of subexpressions are unsequenced.
Reading an object's value to determine where to store it does not count as "determining the value to be stored". This means that the only point of contention can be whether or not we are "modifying" the object i: if we are, it is undefined; if we are not, it is OK.
Does storing the value 0 into an object which already contains the value 0 count as "modifying the stored value"? By the plain English definition of "modify" I would have to say not; leaving something unchanged is the opposite of modifying it.
It is, however, clear that this would be undefined behaviour:
int i = 0, *a = &i;
a[i] = 1;
Here there can be no doubt that the stored value is read for a purpose other than determining the value to be stored (the value to be stored is a constant), and that the value of i is modified.

Resources