int i = 7;
i = i++ + 1; // standard says this is undefined behavior
But, according to precedence rules, i = i++ + 1 means i = ((i++) + 1)
i.e, i should be 8. Why does the standard say it's undefined behavior?
It is not the expression at the right of the "=" that causes undefined behaviour.
It is the fact that i is assigned two values in one expression,
once with the "=" operator and once with the "++" operator.
"assigned two values in one expression" - crystal clear. Thanks man!!!
Specifically, a primitive may not be assigned to twice between two
adjacent sequence points. Doing so is undefined behavior.
int i = 0;
int j = 0;
j = ++i;
The above "assigns two values in one expression", but it's allowed
because no single primitive variable is assigned to two or more
times.
int i = 0;
i = ++i;
The above is not allowed. i is assigned two twice between two adjacent
sequence points.
Further example:
void foo(int& x, int& y)
{ x = ++y; //undefined behavior if x aliases y.
}
int main()
{ int a = 0, b = 0;
foo(a, b); //fine
foo(a, a); //undefined behavior.
}
Because it does. It could just as easily have said that it was
defined behavior (as do other languages). But it prefers to
allow the implementation additional leeway with regards to when
side effects actually occur, and such things. Supposedly, this
allows for better optimization (although I've never seen a case
where it would make a difference, and the compiler couldn't have
done it anyway under the as if rule).
--
James Kanze
> > > Smart Tag <guru.mu...@gmail.com> typed
> > > (in 98d29a45-5656-41b7-ab13-6637f1dd5...@p8g2000yqb.googlegroups.com)
> > > > Consider this:
> > > > int i = 7;
> > > > i = i++ + 1; // standard says this is undefined behavior
> > > > But, according to precedence rules, i = i++ + 1 means i
> > > > = ((i++) + 1) i.e, i should be 8. Why does the standard
> > > > say it's undefined behavior?
> > > It is not the expression at the right of the "=" that
> > > causes undefined behaviour. It is the fact that i is
> > > assigned two values in one expression, once with the "="
> > > operator and once with the "++" operator.
> > "assigned two values in one expression" - crystal clear.
> > Thanks man!!!
> Specifically, a primitive may not be assigned to twice between
> two adjacent sequence points. Doing so is undefined behavior.
To be complete, if a primitive is modified in an expression, it
may not be accessed (read or write) without an intervening
sequence point, other than a read-only access used to determine
the new value. Thus:
int i, j;
j = i + ++i; // undefined behavior !
i = i + 2; // defined, since the read access is
// used to determine the value written.
> Further example:
> void foo(int& x, int& y)
> { x = ++y; //undefined behavior if x aliases y.}
> int main()
> { int a = 0, b = 0;
> foo(a, b); //fine
> foo(a, a); //undefined behavior.
> }
Yes. This can be a real problem.
--
James Kanze
Since calling a function is a sequence point, then I suppose this is
well-defined:
i = somefunction(i++, 1);
Does that mean that if 'i' is of a type for which operator+ has been
defined, it makes "i = i++ + 1;" well-defined?
Yes.
> Does that mean that if 'i' is of a type for which operator+ has been
> defined, it makes "i = i++ + 1;" well-defined?
Well... Expression 'i++' has to yield the type "for which operator+ has
been defined", not 'i'. Of course it is reasonable to expect that those
are the same type. If so, then yes, of course.
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
> Since calling a function is a sequence point, then I suppose this is
> well-defined:
> i = somefunction(i++, 1);
Yes.
> Does that mean that if 'i' is of a type for which operator+
> has been defined, it makes "i = i++ + 1;" well-defined?
Yes.
Just because something is well defined, of course, doesn't mean
that you have to do it:-). Modifying the same (or even
different) variable twice in the same expression makes the code
harder to read and to understand.
--
James
> > Since calling a function is a sequence point, then I suppose this is
> > well-defined:
> > i = somefunction(i++, 1);
> Yes.
> > Does that mean that if 'i' is of a type for which operator+ has been
> > defined, it makes "i = i++ + 1;" well-defined?
> Well... Expression 'i++' has to yield the type "for which
> operator+ has been defined", not 'i'.
That's a good point, which I missed. If operator+ is user
defined, then so is operator++. So the only modification of i
here is the assignment (and unless the result of i++ + 1 is an
enum type, I think that has to be user defined as
well---although it sounds strange when expressed thusly, the
compiler generated assignment for class types is "user
defined"). So what his expression really is (supposing i is a
class type) is:
i.operator=( operator+( i.operator++(0), 1 ) );
or
i.operator=( i.operator++(0).operator+( 1 ) );
With sequence points all over the place, but no modification of
any variable (in the expression directly---if the various
functions take a non-const reference, which is to be expected,
then they might modify the variable).
--
James Kanze