# Is the following expression undefined behavior ?

Discussion in 'C Programming' started by Neroku, Feb 9, 2007.

1. ### NerokuGuest

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

Neroku, Feb 9, 2007

2. ### Walter RobersonGuest

In article <>,
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.

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)

Walter Roberson, Feb 9, 2007

3. ### Kenneth BrodyGuest

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: <mailto:>

Kenneth Brody, Feb 9, 2007
4. ### Flash GordonGuest

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

Flash Gordon, Feb 9, 2007
5. ### Keith ThompsonGuest

-cnrc.gc.ca (Walter Roberson) writes:
> In article <>,
> 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.

>
> 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.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.

Keith Thompson, Feb 10, 2007
6. ### Serve LaurijssenGuest

"Keith Thompson" <> wrote in message
news:...
> -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?

Serve Laurijssen, Feb 10, 2007
7. ### =?utf-8?B?SGFyYWxkIHZhbiBExLNr?=Guest

Serve Laurijssen wrote:
> "Keith Thompson" <> wrote in message
> news:...
> > -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.

=?utf-8?B?SGFyYWxkIHZhbiBExLNr?=, Feb 10, 2007
8. ### Flash GordonGuest

Harald van DÄ³k wrote, On 10/02/07 16:16:
> Serve Laurijssen wrote:
>> "Keith Thompson" <> wrote in message
>> news:...
>>> -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

Flash Gordon, Feb 10, 2007
9. ### =?utf-8?B?SGFyYWxkIHZhbiBExLNr?=Guest

Flash Gordon wrote:
> Harald van DÄ³k wrote, On 10/02/07 16:16:
> > Serve Laurijssen wrote:
> >> "Keith Thompson" <> wrote in message
> >> news:...
> >>> -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.)

=?utf-8?B?SGFyYWxkIHZhbiBExLNr?=, Feb 10, 2007
10. ### Keith ThompsonGuest

"Serve Laurijssen" <> writes:
> "Keith Thompson" <> wrote in message
> news:...
>> -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) <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.

Keith Thompson, Feb 11, 2007

Harald van DÄ³k wrote:
[regarding undefined behavior for x = (i = 3) * i;]
>
> 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.

A compiler may additionally support non-conforming modes which define
the behavior for such constructs.

--

> Harald van DÄ³k wrote:
> [regarding undefined behavior for x = (i = 3) * i;]
>
>>
>> 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.

>
> A compiler may additionally support non-conforming modes which define
> the behavior for such constructs.

Or a conforming mode which defines the behavior for such constructs.

--

13. ### Flash GordonGuest

Thad Smith wrote, On 12/02/07 05:48:
> Harald van DÄ³k wrote:
> [regarding undefined behavior for x = (i = 3) * i;]
>>
>> 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.

>
> A compiler may additionally support non-conforming modes which define
> the behavior for such constructs.

Defining behaviour for such constructs would not make it non-conforming.
Implementations are allowed to define what the C standard leave undefined.
--
Flash Gordon

Flash Gordon, Feb 12, 2007