Velocity Reviews > Is the following expression undefined behavior ?

# Is the following expression undefined behavior ?

Neroku
Guest
Posts: n/a

 02-09-2007
I don't know if the following expression is UB:

i=2;
x = (i=3) * i;

Since in C, evaluation order is unspecified, this expression is 'at
least' unspecified, since we don't know which operand evalutes first,
(i=3) or i, So, would x be always 6 or 9 ? depending on the evaluation
order.

TIA

Walter Roberson
Guest
Posts: n/a

 02-09-2007
In article <(E-Mail Removed) .com>,
Neroku <(E-Mail Removed)> wrote:
>I don't know if the following expression is UB:

>i=2;
>x = (i=3) * i;

>Since in C, evaluation order is unspecified, this expression is 'at
>least' unspecified, since we don't know which operand evalutes first,
>(i=3) or i, So, would x be always 6 or 9 ? depending on the evaluation
>order.

The relevant wording in C89 (ANSI X3.159-1989) is,

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. [34]

with footnote:

[34] This paragraph renders undefined statement expressions such as
i = ++i + 1;
while allowing
i = i + 1;

This wording occurs in a main heading for the description of the
operators, and in my interpretation must be treated as equivilent
as a constraint. But we can answer the question more directly without
resorting to interpretations: notice that the footnote specifically
says that "renders undefined", so the behaviour is "undefined",
not merely "unspecified".
--
"law -- it's a commodity"
-- Andrew Ryan (The Globe and Mail, 2005/11/26)

Kenneth Brody
Guest
Posts: n/a

 02-09-2007
Neroku wrote:
>
> I don't know if the following expression is UB:
>
> i=2;
> x = (i=3) * i;
>
> Since in C, evaluation order is unspecified, this expression is 'at
> least' unspecified, since we don't know which operand evalutes first,
> (i=3) or i, So, would x be always 6 or 9 ? depending on the evaluation
> order.

While most implementations will probably give you one of those
values, the definition of UB means that you can't guarantee it.

Consider a platform capable of parallel operations, and the code
generated includes these two operations to be carried out in
parallel:

stor 3,i ; store 3 in i
mult 3,i,a1 ; multiply i by 3, return in register a1

This could generate a hardware fault, as &i is accessed for both
read and write at the same time.

While most UB examples include modifying an item twice between
sequence points, as in:

i = i++;
or
x = i++ + ++i;

I believe that the UB in question is really "modified, and accessed
for some purpose other than determining the value to modify" (or
similar phrasing), so the following is UB as well:

x = i++ + i;

If I'm wrong (though I don't believe that I am), I'm sure someone
will correct me shortly.

--
+-------------------------+--------------------+-----------------------+
| Kenneth J. Brody | www.hvcomputer.com | #include |
| kenbrody/at\spamcop.net | www.fptech.com | <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------+
Don't e-mail me at: <(E-Mail Removed)>

Flash Gordon
Guest
Posts: n/a

 02-09-2007
Neroku wrote, On 09/02/07 17:51:
> I don't know if the following expression is UB:
>
> i=2;
> x = (i=3) * i;
>
> Since in C, evaluation order is unspecified, this expression is 'at
> least' unspecified, since we don't know which operand evalutes first,
> (i=3) or i, So, would x be always 6 or 9 ? depending on the evaluation
> order.

Evaluation order is not the problem here. The problem is that you read
"i" for a reason other than determining its new value. So it is
undefined behaviour and you could get any value or a crash or wreck the
process due to a bus clash when it tries to simultaneously read and
write "i".
--
Flash Gordon

Keith Thompson
Guest
Posts: n/a

 02-10-2007
http://www.velocityreviews.com/forums/(E-Mail Removed)-cnrc.gc.ca (Walter Roberson) writes:
> In article <(E-Mail Removed) .com>,
> Neroku <(E-Mail Removed)> wrote:
>>I don't know if the following expression is UB:

>
>>i=2;
>>x = (i=3) * i;

>
>>Since in C, evaluation order is unspecified, this expression is 'at
>>least' unspecified, since we don't know which operand evalutes first,
>>(i=3) or i, So, would x be always 6 or 9 ? depending on the evaluation
>>order.

>
> The relevant wording in C89 (ANSI X3.159-1989) is,
>
> 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. [34]
>
> with footnote:
>
> [34] This paragraph renders undefined statement expressions such as
> i = ++i + 1;
> while allowing
> i = i + 1;
>
>
> This wording occurs in a main heading for the description of the
> operators, and in my interpretation must be treated as equivilent
> as a constraint. But we can answer the question more directly without
> resorting to interpretations: notice that the footnote specifically
> says that "renders undefined", so the behaviour is "undefined",
> not merely "unspecified".

No, it's not a constraint, since it's not marked as one. The standard
says:

If a "shall" or "shall not" requirement that appears outside of a
constraint is violated, the behavior is undefined.

which applies in this case.

Constraint violations must be diagnosed at compile time, which is not
possible in general for this requirement. Rather than this:
x = (i = 3) * i;
consider this:
x = (*p1 = 3) * *p2;
It's not possible to determine at compile time whether *p1 and *p2 are
the same object. If they aren't, there's nothing wrong with the
statement.

--
Keith Thompson (The_Other_Keith) http://www.velocityreviews.com/forums/(E-Mail Removed) <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.

Serve Laurijssen
Guest
Posts: n/a

 02-10-2007

"Keith Thompson" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> (E-Mail Removed)-cnrc.gc.ca (Walter Roberson) writes:
> Constraint violations must be diagnosed at compile time, which is not
> possible in general for this requirement. Rather than this:
> x = (i = 3) * i;
> consider this:
> x = (*p1 = 3) * *p2;

well in general its not possible indeed, but can the compiler give an error
when it knows for certain it's the same object?
or warning at most?

=?utf-8?B?SGFyYWxkIHZhbiBExLNr?=
Guest
Posts: n/a

 02-10-2007
Serve Laurijssen wrote:
> "Keith Thompson" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...
> > (E-Mail Removed)-cnrc.gc.ca (Walter Roberson) writes:
> > Constraint violations must be diagnosed at compile time, which is not
> > possible in general for this requirement. Rather than this:
> > x = (i = 3) * i;
> > consider this:
> > x = (*p1 = 3) * *p2;

>
> well in general its not possible indeed, but can the compiler give an error
> when it knows for certain it's the same object?
> or warning at most?

A compiler in conforming mode may not refuse to compile it, unless it
can prove that the code will always be executed. And naturally, a
compiler may additionally support non-conforming modes in which such
code does cause a hard error.

Flash Gordon
Guest
Posts: n/a

 02-10-2007
Harald van Dĳk wrote, On 10/02/07 16:16:
> Serve Laurijssen wrote:
>> "Keith Thompson" <(E-Mail Removed)> wrote in message
>> news:(E-Mail Removed)...
>>> (E-Mail Removed)-cnrc.gc.ca (Walter Roberson) writes:
>>> Constraint violations must be diagnosed at compile time, which is not
>>> possible in general for this requirement. Rather than this:
>>> x = (i = 3) * i;
>>> consider this:
>>> x = (*p1 = 3) * *p2;

>> well in general its not possible indeed, but can the compiler give an error
>> when it knows for certain it's the same object?
>> or warning at most?

>
> A compiler in conforming mode may not refuse to compile it, unless it
> can prove that the code will always be executed. And naturally, a
> compiler may additionally support non-conforming modes in which such
> code does cause a hard error.

The compiler is allowed to produce a warning for it, since compilers are
allowed to warn anything they want.
--
Flash Gordon

=?utf-8?B?SGFyYWxkIHZhbiBExLNr?=
Guest
Posts: n/a

 02-10-2007
Flash Gordon wrote:
> Harald van Dĳk wrote, On 10/02/07 16:16:
> > Serve Laurijssen wrote:
> >> "Keith Thompson" <(E-Mail Removed)> wrote in message
> >> news:(E-Mail Removed)...
> >>> (E-Mail Removed)-cnrc.gc.ca (Walter Roberson) writes:
> >>> Constraint violations must be diagnosed at compile time, which is not
> >>> possible in general for this requirement. Rather than this:
> >>> x = (i = 3) * i;
> >>> consider this:
> >>> x = (*p1 = 3) * *p2;
> >> well in general its not possible indeed, but can the compiler give an error
> >> when it knows for certain it's the same object?
> >> or warning at most?

> >
> > A compiler in conforming mode may not refuse to compile it, unless it
> > can prove that the code will always be executed. And naturally, a
> > compiler may additionally support non-conforming modes in which such
> > code does cause a hard error.

>
> The compiler is allowed to produce a warning for it, since compilers are
> allowed to warn anything they want.

Right, so long as the warning does not cause the compilation to fail
in any of the compiler's modes that are meant to be conforming. (A
warning is not necessarily a non-fatal diagnostic, though admittedly
the only cases of fatal warnings in real-world compilers I've seen
were the result of compiler bugs.)

Keith Thompson
Guest
Posts: n/a

 02-11-2007
"Serve Laurijssen" <(E-Mail Removed)> writes:
> "Keith Thompson" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...
>> (E-Mail Removed)-cnrc.gc.ca (Walter Roberson) writes:
>> Constraint violations must be diagnosed at compile time, which is not
>> possible in general for this requirement. Rather than this:
>> x = (i = 3) * i;
>> consider this:
>> x = (*p1 = 3) * *p2;

>
> well in general its not possible indeed, but can the compiler give an error
> when it knows for certain it's the same object?
> or warning at most?

Of course, the compiler can give a warning for anything it likes, and
it can give a fatal error if it can prove that it will always invoke
undefined behavior (not, for example, if the statement is enclosed in
"if (0) { ... }". But since it's not a constraint violation, it's not
required to do so, even when it happens to be easy to figure it out at
compile time.

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.