strange feature... or bug

Discussion in 'C Programming' started by sonic, Aug 28, 2007.

  1. sonic

    sonic Guest

    Please tell me what is wrong (and for me to avoid browsing through
    200k something messages
    ) or am i missing something obvious (btw i've tested with gcc on
    latest Tiger OS X and linux); or should i post to gcc?

    ---------------------------
    #include <stdio.h>

    int main()
    {
    int i = 2;
    i = (i*=1 ? i-2 : 0);
    printf("val is %d\n", i);
    return 0;
    }
    --------------------------

    you would expect to print 0 right, it does!

    removed -2, like:

    -------------------------
    #include <stdio.h>

    int main()
    {
    int i = 2;
    i = (i*=1 ? i : 0);
    printf("val is %d\n", i);
    return 0;
    }
    --------------------------
    and it returns ... 4!, while i have expected 2...
     
    sonic, Aug 28, 2007
    #1
    1. Advertising

  2. sonic <> writes:
    > Please tell me what is wrong (and for me to avoid browsing through
    > 200k something messages
    > ) or am i missing something obvious (btw i've tested with gcc on
    > latest Tiger OS X and linux); or should i post to gcc?
    >

    [snip]
    >
    > -------------------------
    > #include <stdio.h>
    >
    > int main()
    > {
    > int i = 2;
    > i = (i*=1 ? i : 0);
    > printf("val is %d\n", i);
    > return 0;
    > }
    > --------------------------
    > and it returns ... 4!, while i have expected 2...


    I'll just address your second example.

    In both programs, you modify 'i' twice between sequence points,
    invoking undefined behavior.

    Also, the spacing in your expression is inconsistent with the actual
    operator precedence. The '?:' operator binds more tightly than an
    assignment operator. Your statement
    i = (i*=1 ? i : 0);
    is equivalent to
    i = (i *= (1 ? i : 0));
    The subexpression '(1 ? i : 0)' can be reduced to 'i', giving:
    i = (i *= i);
    which still invokes UB.

    If you start by thinking about what you want to do, and then write C
    code to express your intent, you'll never write anything like that in
    the first place.

    --
    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."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Aug 28, 2007
    #2
    1. Advertising

  3. Re: strange feature... or bug

    On Aug 28, 4:06 pm, sonic <> wrote:
    > Please tell me what is wrong (and for me to avoid browsing through
    > 200k something messages
    > ) or am i missing something obvious (btw i've tested with gcc on
    > latest Tiger OS X and linux); or should i post to gcc?
    >
    > ---------------------------
    > #include <stdio.h>
    >
    > int main()
    > {
    > int i = 2;
    > i = (i*=1 ? i-2 : 0);
    > printf("val is %d\n", i);
    > return 0;}
    >
    > --------------------------
    >
    > you would expect to print 0 right, it does!
    >
    > removed -2, like:
    >
    > -------------------------
    > #include <stdio.h>
    >
    > int main()
    > {
    > int i = 2;
    > i = (i*=1 ? i : 0);
    > printf("val is %d\n", i);
    > return 0;}
    >
    > --------------------------
    > and it returns ... 4!, while i have expected 2...


    Both examples contain undefined behavior because i is assigned to
    multiple times without an intervening sequence point. The problem is
    that this may not be readily apparent in your example because of the
    precedences of the of the *= and conditional operators. This line:

    i = (i*=1 ? i : 0);

    is equivalent to this one:

    i = (i*= (1 ? i : 0));

    which is equivalent to this:

    i = i* = (1 ? i : 0);

    Since this is undefined behavior anything is allowed although it
    should be easy to see why the subexpression (which doesn't contain
    UB):

    i* = (1 ? i : 0);

    would yield 4.

    Robert Gamble
     
    Robert Gamble, Aug 28, 2007
    #3
  4. sonic

    sonic Guest

    Re: strange feature... or bug

    Many thanks for both of your answers Keith and Rob




    > In both programs, you modify 'i' twice between sequence points,
    > invoking undefined behavior.

    oops


    > operator precedence. The '?:' operator binds more tightly than an
    > assignment operator. Your statement


    Many thanks! i understand it now!
    > i = (i *= i);


    > If you start by thinking about what you want to do, and then write C
    > code to express your intent, you'll never write anything like that in
    > the first place.

    Actually i was just studying Confuscated C code and tried to exercie
    mine a little bit and missed an obvious case with the precedence!
     
    sonic, Aug 28, 2007
    #4
  5. sonic

    Ark Khasin Guest

    Keith Thompson wrote:
    <snip>
    > In both programs, you modify 'i' twice between sequence points,
    > invoking undefined behavior.
    >
    > Also, the spacing in your expression is inconsistent with the actual
    > operator precedence. The '?:' operator binds more tightly than an
    > assignment operator. Your statement
    > i = (i*=1 ? i : 0);
    > is equivalent to
    > i = (i *= (1 ? i : 0));
    > The subexpression '(1 ? i : 0)' can be reduced to 'i', giving:
    > i = (i *= i);
    > which still invokes UB.
    >

    <snip>

    Just wondering:
    i = (i<2007)?(i+=0):(i*=1);
    Is it still UB?
    Or must an expression evaluate to one of the finite set of values
    determined by the freedom of compiler's choice in the order of evaluation?
    -- Ark
     
    Ark Khasin, Aug 29, 2007
    #5
  6. Ark Khasin <> writes:
    > Keith Thompson wrote:
    > <snip>
    >> In both programs, you modify 'i' twice between sequence points,
    >> invoking undefined behavior.
    >> Also, the spacing in your expression is inconsistent with the actual
    >> operator precedence. The '?:' operator binds more tightly than an
    >> assignment operator. Your statement
    >> i = (i*=1 ? i : 0);
    >> is equivalent to
    >> i = (i *= (1 ? i : 0));
    >> The subexpression '(1 ? i : 0)' can be reduced to 'i', giving:
    >> i = (i *= i);
    >> which still invokes UB.
    >>

    > <snip>
    >
    > Just wondering:
    > i = (i<2007)?(i+=0):(i*=1);
    > Is it still UB?
    > Or must an expression evaluate to one of the finite set of values
    > determined by the freedom of compiler's choice in the order of
    > evaluation?


    That case (and the others) is slightly complicated by the fact that
    there's a sequence point after the evaluation of the first operand of
    a conditional operator. Nevertheless, I'm reasonably sure the
    behavior is undefined.

    --
    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."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Aug 29, 2007
    #6
  7. sonic

    Flash Gordon Guest

    Keith Thompson wrote, On 29/08/07 05:35:
    > Ark Khasin <> writes:
    >> Keith Thompson wrote:
    >> <snip>
    >>> In both programs, you modify 'i' twice between sequence points,
    >>> invoking undefined behavior.
    >>> Also, the spacing in your expression is inconsistent with the actual
    >>> operator precedence. The '?:' operator binds more tightly than an
    >>> assignment operator. Your statement
    >>> i = (i*=1 ? i : 0);
    >>> is equivalent to
    >>> i = (i *= (1 ? i : 0));
    >>> The subexpression '(1 ? i : 0)' can be reduced to 'i', giving:
    >>> i = (i *= i);
    >>> which still invokes UB.
    >>>

    >> <snip>
    >>
    >> Just wondering:
    >> i = (i<2007)?(i+=0):(i*=1);
    >> Is it still UB?
    >> Or must an expression evaluate to one of the finite set of values
    >> determined by the freedom of compiler's choice in the order of
    >> evaluation?

    >
    > That case (and the others) is slightly complicated by the fact that
    > there's a sequence point after the evaluation of the first operand of
    > a conditional operator. Nevertheless, I'm reasonably sure the
    > behavior is undefined.


    Unless there is a sequence point after the evaluation of the second or
    third argument then it is definitely UB. I believe there is no such
    sequence point, so like you I am reasonably sure it is UB.
    --
    Flash Gordon
     
    Flash Gordon, Aug 29, 2007
    #7
    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. Shel Blauman [MSFT]

    Re: feature or bug?

    Shel Blauman [MSFT], Aug 11, 2003, in forum: ASP .Net
    Replies:
    0
    Views:
    413
    Shel Blauman [MSFT]
    Aug 11, 2003
  2. Replies:
    14
    Views:
    1,502
  3. Carlos Ribeiro
    Replies:
    10
    Views:
    511
    Peter Hansen
    Sep 15, 2004
  4. john

    compiler bug / strange language feature

    john, Mar 24, 2010, in forum: C Programming
    Replies:
    17
    Views:
    501
    Tim Rentsch
    Mar 27, 2010
  5. robic0
    Replies:
    7
    Views:
    111
    Samwyse
    Jan 24, 2006
Loading...

Share This Page