Is the following expression undefined behavior ?

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

  1. Neroku

    Neroku Guest

    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
    #1
    1. Advertising

  2. 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
    #2
    1. Advertising

  3. 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
    #3
  4. Neroku

    Flash Gordon Guest

    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
    #4
  5. -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
    #5
  6. "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
    #6
  7. 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
    #7
  8. Neroku

    Flash Gordon Guest

    Harald van Dijk 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
    #8
  9. Flash Gordon wrote:
    > Harald van Dijk 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
    #9
  10. "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
    #10
  11. Neroku

    Thad Smith Guest

    Harald van Dijk 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.

    --
    Thad
    Thad Smith, Feb 12, 2007
    #11
  12. Neroku

    Thad Smith Guest

    Thad Smith wrote:
    > Harald van Dijk 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.

    --
    Thad
    Thad Smith, Feb 12, 2007
    #12
  13. Neroku

    Flash Gordon Guest

    Thad Smith wrote, On 12/02/07 05:48:
    > Harald van Dijk 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
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mantorok Redgormor
    Replies:
    70
    Views:
    1,731
    Dan Pop
    Feb 17, 2004
  2. grocery_stocker
    Replies:
    7
    Views:
    224
  3. Chad

    Is the following undefined behavior

    Chad, Feb 21, 2011, in forum: C Programming
    Replies:
    2
    Views:
    213
    Eric Sosman
    Feb 21, 2011
  4. VK
    Replies:
    45
    Views:
    578
    Dr John Stockton
    Sep 12, 2006
  5. Wake up Brazil
    Replies:
    10
    Views:
    111
    Öö Tiib
    Apr 16, 2014
Loading...

Share This Page