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.
Related
This question already has answers here:
Undefined behavior and sequence points
(5 answers)
Closed 8 years ago.
My teacher provided me with this code and it returns 31,40, but I am unable to figure out why. What is the reason for it returning what it does?
void main() {
int *ptr;
int arr[5] = { 10, 20, 30, 40, 50 };
ptr = &arr[3];
cout << ++*ptr-- << ", " << *ptr;
}
cout << ++*ptr-- << ", " << *ptr;
is
operator <<(cout.operator <<(++*ptr--), ", ").operator <<(*ptr);
The problem can be reduced to:
f(f(ptr--), ptr)
whereas order of evaluation between f(ptr--) and ptr is unspecified (and more specificaly between ptr-- and ptr).
So you got undefined behavior for the given code.
The C++ standard states
Section 1.9/15 [intro.execution] : Except where noted, evaluations of operands of individual operators and of subexpressions of individual
expressions are unsequenced. (...) If a side effect on a scalar object is unsequenced relative to either another side effect on the
same scalar object or a value computation using the value of the same
scalar object, the behavior is undefined.
++*ptr-- and *ptr are unsequenced subexpressions of the same expression using the same object: nothing guarantees that they are evaluated from left to right. So according to the standard, this results in undefined behaviour. Your result tend to show that your compiler chooses to evaluate first *ptr and then ++*ptr--.
Edit: ++*ptr-- is ++(*ptr--)). Here the operand of operator ++ also uses object ptr on which -- does a side effect. So this is undefined behaviour as well. It appears that in your case, the compiler first evaluates *ptr-- which results in 40 and a decremented ptr, and then applies ++ on the dereferenced decremented pointer (i.e. 30 incremented by 1).
Is there a way in C and C++ to cause functions returning void to be evaluated in unspecified order?
I know that function arguments are evaluated in unspecified order so for functions not returning void this can be used to evaluate those functions in unspecified order:
#include <stdio.h>
int hi(void) {
puts("hi");
return 0;
}
int bye(void) {
puts("bye");
return 0;
}
int moo(void) {
puts("moo");
return 0;
}
void dummy(int a, int b, int c) {}
int main(void) {
dummy(hi(), bye(), moo());
}
Legal C and C++ code compiled by a conforming compiler may print hi, bye, and moo in any order. This is not undefined behavior (nasal demons would not be valid), there is simply more than one but less than infinite valid outputs and a compliant compiler need not even be deterministic in what it produces.
Is there any way to do this without the dummy return values?
Clarification: This is an abstract question about C and C++. A better original phrasing might have been is there any context in which function evaluation order is unspecified for functions returning void? I'm not trying to solve a specific problem.
You can take advantage of the fact that the left hand side of a the comma operator is a discarded value expression (void expression in C) like this (see it live):
int main(void) {
dummy((hi(),0), (bye(),0), (moo(),0));
}
From the draft C++ standard section 5.18 Comma operator:
A pair of expressions separated by a comma is evaluated left-to-right; the left expression is a discarded-value expression (Clause 5).
and C11 section 6.5.17 Comma operator:
The left operand of a comma operator is evaluated as a void expression; there is a
sequence point between its evaluation and that of the right operand. Then the right
operand is evaluated; the result has its type and value.
As Matt points out is is also possible to mix the above method with arithmetic operators to achieve unspecified order of evaluation:
(hi(),0) + (bye(),0) + (moo(),0) ;
Well there's always the obvious approach of putting pointers to the functions in a container, shuffling it up (or as suggested in a comment sorting it), and calling each item in the container. If you need to have the same behavior each run just make sure your seed is the same each time.
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.
This question already has answers here:
Undefined behavior and sequence points
(5 answers)
Closed 9 years ago.
I do not understand why the output of following program is 63:
#include <iostream>
int main() {
int a = 20;
a += a + ++a;
std::cout << a;
}
I was expecting it to be 61. What exactly a += a + ++a; does?
Standard 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" (5 Expressions, §4), i.e. the following:
a += a + ++a
yields undefined behavior just like:
a = ++a;
does already. It also says: "the prior value shall be accessed only to determine the value to be stored", i.e. if you want to change a, you can use a in the same expression just to retrieve the previous value:
a = a + 1; // OK
... "otherwise the behavior is undefined."
You're triggering undefined behavior and there is no 'correct' answer. Your compiler can chose what order to evaluate the arguments of the plus operator.
it looks like ++a is evaluating before the rest of the expression, so it's as though a is 21` in a statement like
a += a + a;
at any rate, don't use ++a inside of an arithmetic expression like that anyway. It's confusing for people, and is probably undefined behavior
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.