Why is this statement not changin the array? [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.
int a[]={1,2,3,5};
int i=1;
a[++i]=a[i];
int j;
for(j=0;j<4;j++)
{
printf("%d",a[j]);
}
output:1235;
why the output is 1225 and not 1335.
I executed this program on codeblocks. In a[++i]=a[i], Right to left assignment will be their,leading to a[2]=a[1]. Correct me if i am wrong.

Because a[++i]=a[i]; is undefined behavior.
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.

a[++i]=a[i]; // this is undefined
If you only want to change single element of the array ... do it by referencing it directly:
int a[]={1,2,3,5};
int i=1;
a[i]++; // this will increment the ith element of the array by 1
int j;
for(j=0;j<4;j++)
{
printf("%d",a[j]);
}
Output:
1335

a[++i]=a[i]; is undefined behavior. Because according to C99 section 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.72) Furthermore, the prior value shall be read only to
determine the value to be stored.73)
= is not a sequence point. Check annex C.
You are modifying the value i one time, but "the prior value shall be read only to determine the value to be stored" is violated as you do a[++i].
Check Footnote 73) for an example of what the paragraph says.
73)This paragraph renders undefined statement expressions such as
i = ++i + 1;
a[i++] = i;
while allowing
i = i + 1;
a[i] = i;
Therefore what the outcome will be cannot be determined. For different run and/or across different computers you can get different results. Such kind of expressions should not be used in C programming.

a[++i] = a[i] is undefined behavior. look-up this presentation.

Related

why i = ++i + 2 is undefined behavior? [duplicate]

This question already has answers here:
New Sequence Points in C++11
(2 answers)
So why is i = ++i + 1 well-defined in C++11?
(3 answers)
Closed 4 years ago.
I've read something about order of evaluation and I understand some mistakes caused by order of evaluation.
My basic rule comes from a text and example:
Order of operand evaluation is independent of precedence and associativity.
In most cases, the order is largely unspecified.
So for expression like this: int i = f1() * f2();
f1 and f2 must be called before the multiplication can be done. After all, it is their results that are multiplied. However, we have no way of knowing whether f1 will be called before f2 or vice versa.
Undefined behavior examples:
int i = 0;
cout << i << " " << ++i << endl;
How I understand: I treat i and ++i as a function. I don't know which evaluates first, so the first i could be 0 or 1 and (the rule) makes sense.
while(beg != s.end())
*beg = toupper(*beg++); //Just another example.
I think the key to understand this is to treat each operand as a "evaluation unit", and one don't know order of evaluation within these units but can know order in every single unit.
But for i = ++i + 2 reference here, Why is it wrong? I can't explain with my own conclusion.
The left i is used as a lvalue and not a pointer. ++i simply rewrite the original value and doesn't change the storage address. What could be wrong if it evaluates first or latter? My rule fails here.
Quite long but try to provide enough background info, thank for your patience.
I don't know sequence point which is mentioned frequently in answers.. So I think I need to read something about it first. Btw, the debate is not very helpful, for a newbie simply want to know why is it considered wrong, like before C++11?
I find this answer Undefined behavior and sequence points explain well why i = ++i + 2 is undefined behaviour before C++11
C++11 has new sequencing rules. In particular, for a pre-increment (++i) the side effect (writing the new value) is sequenced-before the further use of the new, incremented value. Since the assignment i= is sequenced-after the evaluation of its right-hand side, this means the write ++i is transitively sequenced-before the write i=(++i + 2)
It would be another matter for i=(i++ + 2). For post-increment, the side effect is sequenced-after, which means the two assignments are no longer sequenced relatively to each other. That IS undefined behavior.
Your two "subfunctions" in i = ++i + 2 are an explicit assignment made by the = operator and an implicit assignment done by the ++ operator.
The preincrement operator is defined to return an incremented value of the variable, and this definitely shall be used for addition (performed by the + operator). However, it was not defined, when the incremented value should be stored back into i.
As a result, it was undefined whether the final value of i is old_i incremented plus 2 or just old_i incremented.

operator precedence [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
cout << order of call to functions it prints?
Undefined Behavior and Sequence Points
Why does this code print 2 1 0?
#include <iostream>
struct A{
int p;
A():p(0){}
int get(){
return p++;
}
};
int main(){
A a;
std::cout<<a.get()<<" "<<a.get()<<" "<<a.get()<<std::endl;
}
As I stated in my comment, there's no sequence point...
According to §6.2.2 of Stroustrup's The C++ Programming Language, Third Edition...
The order of evaluation of subexpressions within an expression is undefined. In particular, you cannot assume that the expression is evaluated left to right.
§5.4 of the C++03 standard specifies:
Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified. 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.
You can learn more about sequence points and undefined behavior here.

Is array[i] = i++ covered by the C++ standard?

I had a person claiming that this line is not covered by the C++ standard:
int i(1);
array_of_int[i] = i++;
The person said that it will assign 1 but we cannot know whether it will be in array_of_int[1] or array_of_int[2] although visual studio and most of compilers will be in array_of_int[1].
Is he correct ?
This is undefined behavior. Literally any behavior is legal.
The passage that forbids that line of code is this:
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 between a[i] and i++ and the read to i in a[i] is not for the purpose of determining what value is stored in i by i++.

Multiple postfix increment operator in an expression[C++] [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)
I'm having my lecturer class right now and my lecturer mention an expression as follows:
int a , b;
a = 4;
b = a++ + a--;
The Question
My lecturer says this expression value can be defined: that it is 8. Which means both a value 4 is summed and assign to b before it's incremented and decremented.
But to me, I think this expression answer is kinda vague and the result will be based on the compiler implementation. That's because to me, the compiler might do the a++ part first—that is, use the value 4 and incremented the a to 5, after that the expression is 4 + 5 = 9 and is assigned to b then only the a is decremented.
It might also do the a-- part first by using the value 4 and decremented it by 1 to 3, and later on sum the value 4 with 3 and assign the value to b then only incremented the a back to 4.
My question is who's correct, my lecturer or me? Because I don't wanna get confused with it and later on will be a problem for me.
Your lecturer is wrong. Writing to the same variable twice without an intervening sequence point is undefined behaviour. From the spec, J.2 Undefined behaviour:
Between two sequence points, an object is modified more than once, or is modified and the prior value is read other than to determine the value to be stored (6.5).
The reference is to 6.5 Expressions, paragraph 5:
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.
Annex C of the C spec has a handy list of all of the sequence points:
The following are the sequence points described in 5.1.2.3:
The call to a function, after the arguments have been evaluated (6.5.2.2).
The end of the first operand of the following operators: logical AND && (6.5.13); logical OR || (6.5.14); conditional ? (6.5.15); comma , (6.5.17).
The end of a full declarator: declarators (6.7.5);
The end of a full expression: an initializer (6.7.8); the expression in an expression statement (6.8.3); the controlling expression of a selection statement (if or switch) (6.8.4); the controlling expression of a while or do statement (6.8.5); each of the expressions of a for statement (6.8.5.3); the expression in a return statement (6.8.6.4).
Immediately before a library function returns (7.1.4).
After the actions associated with each formatted input/output function conversion specifier (7.19.6, 7.24.2).
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 (7.20.5).

What would the evaluation order of x = x++ + ++x; be? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)
In Java the evaluation order is specified to be left-to-right. Is this the case for C and C++ as well, or is it implementation dependent? I do remember that the evaluation order is unspecified for function arguments, but what about sub-expressions?
It is unspecified which of the arguments to + is evaluated first - but that doesn't even matter, because in C and C++, modifying the same object twice without an intervening sequence point is completely undefined behaviour.
Here you're modifying x three times without an intervening sequence point, so you're well into here be dragonnes territory ;)
The relevant part of the C99 standard is "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.
and
3 The grouping of operators and
operands is indicated by the
syntax. Except as specified later
(for the function-call (), &&, ||, ?:,
and comma operators), the order of
evaluation of subexpressions and the
order in which side effects take place
are both unspecified.
It's possible to write legal code that demonstrates the unspecified order of evaluation - for example:
#include <stdio.h>
int foo(void)
{
puts("foo");
return 1;
}
int bar(void)
{
puts("bar");
return 2;
}
int main()
{
int x;
x = foo() + bar();
putchar('\n');
return x;
}
(It is unspecified whether you get output of foobar or barfoo).
C++03 Standard 5.4
Except where noted, the order of
evaluation of operands of individual
operators and subexpressions of
individual expressions, and the order
in which side effects take place, is
unspecified.53) 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.
... hence, undefined and implementation dependant.
The C standard does not guarantee that the post-increment will actually "happen" after the pre-increment. So that is undefined behaviour.
That's not a valid C statement, so it doesn't make sense to talk about the evaluation order.