Unexpected output

Discussion in 'C Programming' started by Mazen, Sep 10, 2011.

  1. Mazen

    Mazen Guest

    Hello,

    Following is a simple program:

    #include <stdio.h>

    int main(void) {
    int i = 0, j, k;
    j = k = 2;

    printf("%d %d\n", i=+j, i=-j);

    return 0;
    }

    The output is
    2 2

    Shouldn't the second expression be -2 rather than 2? I'm confused.
    Your insights pls. Thanks!
     
    Mazen, Sep 10, 2011
    #1
    1. Advertising

  2. Mazen

    Mazen Guest

    On Sep 10, 12:59 pm, China Blue Corn Chips <>
    wrote:
    > In article <..com>,
    >
    >
    >
    >
    >
    >
    >
    >
    >
    >  Mazen <> wrote:
    > > Hello,

    >
    > > Following is a simple program:

    >
    > > #include <stdio.h>

    >
    > > int main(void) {
    > >   int i = 0, j, k;
    > >   j = k = 2;

    >
    > >   printf("%d %d\n", i=+j, i=-j);

    >
    > >   return 0;
    > > }

    >
    > > The output is
    > > 2 2

    >
    > > Shouldn't the second expression be -2 rather than 2? I'm confused.
    > > Your insights pls. Thanks!

    >
    > The order of evaluation of function arguments is left to the implementation.
    >
    > --
    > I remember finding out about you,  |With the nutty taste of wild hickory nuts.
    > Everyday my mind is all around you,|            I'm whoever you want me to be.
    > Looking out from my lonely room    |       Annoying Usenet one post at a time.
    > Day after day.                     |         At least I can stay in character.
    > Celle est une langue. C'est francais et tres, tres sexuel.


    Not sure I understood what you mean.
     
    Mazen, Sep 10, 2011
    #2
    1. Advertising

  3. Mazen

    arni Guest

    On Sep 10, 10:36 pm, Mazen <> wrote:
    > Hello,
    >
    > Following is a simple program:
    >
    > #include <stdio.h>
    >
    > int main(void) {
    >   int i = 0, j, k;
    >   j = k = 2;
    >
    >   printf("%d %d\n", i=+j, i=-j);
    >
    >   return 0;
    >
    > }
    >
    > The output is
    > 2 2
    >
    > Shouldn't the second expression be -2 rather than 2? I'm confused.
    > Your insights pls. Thanks!


    Shouldn't it be i+=j and i-=j?.. Then you'll get 2 -2.
     
    arni, Sep 10, 2011
    #3
  4. Mazen

    Eric Sosman Guest

    On 9/10/2011 3:59 PM, China Blue Corn Chips wrote:
    > In article<>,
    > Mazen<> wrote:
    >[...]
    >> printf("%d %d\n", i=+j, i=-j);
    >> [...]
    >> The output is
    >> 2 2
    >>
    >> Shouldn't the second expression be -2 rather than 2? I'm confused.
    >> Your insights pls. Thanks!

    >
    > The order of evaluation of function arguments is left to the implementation.


    It's more serious than that: The behavior is undefined. The
    line in question tries to assign to `i' twice without an intervening
    sequence point, and the C language makes no promises whatsoever about
    what might happen in consequence.

    C has two distinct uses for the comma: as an operator, and as
    a separator. The comma operator involves a defined order and a
    sequence point: `f = x,y' means "first evaluate x and ignore the
    value, sequence point, then evaluate y and yield its value, that
    value is assigned to f." The comma separator just separates the
    elements of a list, without implying any kind of order and without
    imposing sequence points. (Unfortunately, the two uses look
    distressingly similar.)

    In the offending line above, both commas are separators rather
    than operators, so no sequence points divide the argument evaluations
    from each other. In particular, the two assignments to `i' are not
    so divided, hence the undefined behavior.

    --
    Eric Sosman
    d
     
    Eric Sosman, Sep 10, 2011
    #4
  5. Mazen

    Eric Sosman Guest

    On 9/10/2011 4:31 PM, arni wrote:
    > On Sep 10, 10:36 pm, Mazen<> wrote:
    >> [...]
    >> printf("%d %d\n", i=+j, i=-j);
    >> [...]
    >> return 0;

    > [...]
    > Shouldn't it be i+=j and i-=j?.. Then you'll get 2 -2.


    Or not: The behavior would still be undefined, and for the
    same reason as before.

    --
    Eric Sosman
    d
     
    Eric Sosman, Sep 10, 2011
    #5
  6. Mazen

    arni Guest

    On Sep 10, 11:49 pm, Eric Sosman <> wrote:
    > On 9/10/2011 4:31 PM, arni wrote:
    >
    > > On Sep 10, 10:36 pm, Mazen<>  wrote:
    > >> [...]
    > >>    printf("%d %d\n", i=+j, i=-j);
    > >> [...]
    > >>    return 0;

    > > [...]
    > > Shouldn't it be i+=j and i-=j?.. Then you'll get 2 -2.

    >
    >      Or not: The behavior would still be undefined, and for the
    > same reason as before.
    >
    > --
    > Eric Sosman
    >


    Depends on compiler/optimizer implementation. Anyway, writing code
    like that is a very bad practice, you can not be sure what's going to
    happen in the end :)
     
    arni, Sep 10, 2011
    #6
  7. On Sat, 10 Sep 2011 16:31:33 -0400, arni <> wrote:

    > On Sep 10, 10:36 pm, Mazen <> wrote:
    >> Hello,
    >>
    >> Following is a simple program:
    >>
    >> #include <stdio.h>
    >>
    >> int main(void) {
    >>   int i = 0, j, k;
    >>   j = k = 2;
    >>
    >>   printf("%d %d\n", i=+j, i=-j);
    >>
    >>   return 0;
    >>
    >> }
    >>
    >> The output is
    >> 2 2
    >>
    >> Shouldn't the second expression be -2 rather than 2? I'm confused.
    >> Your insights pls. Thanks!

    >
    > Shouldn't it be i+=j and i-=j?.. Then you'll get 2 -2.


    No. If modifying i twice in the argument list weren't undefined,
    so that one assignment to i and the evaluation of the corresponding
    function argument were guaranteed to be complete before the next
    argument was evaluated, printf("%d %d\n", i += j, i -= j) would produce
    either "2 0" or "0 -2", depending on the order in which the arguments
    are evaluated, which is unspecified (not undefined). The poorly-spaced
    code seems to have been intended as printf("%d %d\n", i = +j, i = -j);
    --
    Morris Keesan --
     
    Morris Keesan, Sep 10, 2011
    #7
  8. Mazen

    Eric Sosman Guest

    On 9/10/2011 5:13 PM, arni wrote:
    > On Sep 10, 11:49 pm, Eric Sosman<> wrote:
    >> On 9/10/2011 4:31 PM, arni wrote:
    >>
    >>> On Sep 10, 10:36 pm, Mazen<> wrote:
    >>>> [...]
    >>>> printf("%d %d\n", i=+j, i=-j);
    >>>> [...]
    >>>> return 0;
    >>> [...]
    >>> Shouldn't it be i+=j and i-=j?.. Then you'll get 2 -2.

    >>
    >> Or not: The behavior would still be undefined, and for the
    >> same reason as before.

    >
    > Depends on compiler/optimizer implementation.


    The C language is defined by an International Standard, not by
    the quirks of any individual compiler. The Standard does not define
    any specific behavior for the offending line, nor even any limits on
    the possible behaviors.

    In particular, there's no guarantee that "you'll get 2 -2."

    A particular implementation is free to add (or not) its own
    definitions to cover cases the Standard leaves undefined -- but
    then you're no longer talking about "C," but about "Frobozz Magic
    C Version 4.2 optimization level 3 with #pragma DWIM in effect."

    > Anyway, writing code
    > like that is a very bad practice, you can not be sure what's going to
    > happen in the end :)


    Exactly: "What's going to happen" is not defined by the C language.

    --
    Eric Sosman
    d
     
    Eric Sosman, Sep 10, 2011
    #8
  9. Mazen

    BartC Guest

    "Mazen" <> wrote in message
    news:...

    > #include <stdio.h>
    >
    > int main(void) {
    > int i = 0, j, k;
    > j = k = 2;
    >
    > printf("%d %d\n", i=+j, i=-j);
    >
    > return 0;
    > }
    >
    > The output is
    > 2 2
    >
    > Shouldn't the second expression be -2 rather than 2? I'm confused.


    It *is* unintuitive. But printf() is a function, and sometimes the
    parameters are evaluated in a funny order:

    #include <stdio.h>

    int next(void){static int a=0; return ++a;}

    int main(void){
    printf("%d %d %d\n",next(),next(),next());
    }

    gives 1 2 3 on one compiler, and 3 2 1 on another (and doubtless some
    compiler might give 3 1 2!).

    Changing main() to resemble your code:

    int main(void){
    int i;
    printf("%d %d %d",i=next(),i=next(),i=next());
    }

    Now I get results on 1 2 3, 3 3 3, and 3 2 1 on three different compilers!

    For guaranteed results, you need to use a separate printf() call for each
    term.

    --
    Bartc
     
    BartC, Sep 10, 2011
    #9
  10. Mazen

    Mazen Guest

    Thanks, Eric. So, how can one achieve the desired result and guarantee a defined behavior?
     
    Mazen, Sep 11, 2011
    #10
  11. Mazen

    Mazen Guest

    On Sep 10, 2:26 pm, Eric Sosman <> wrote:
    > On 9/10/2011 5:13 PM, arni wrote:
    >
    > > On Sep 10, 11:49 pm, Eric Sosman<>  wrote:
    > >> On 9/10/2011 4:31 PM, arni wrote:

    >
    > >>> On Sep 10, 10:36 pm, Mazen<>    wrote:
    > >>>> [...]
    > >>>>     printf("%d %d\n", i=+j, i=-j);
    > >>>> [...]
    > >>>>     return 0;
    > >>> [...]
    > >>> Shouldn't it be i+=j and i-=j?.. Then you'll get 2 -2.

    >
    > >>       Or not: The behavior would still be undefined, and for the
    > >> same reason as before.

    >
    > > Depends on compiler/optimizer implementation.

    >
    >      The C language is defined by an International Standard, not by
    > the quirks of any individual compiler.  The Standard does not define
    > any specific behavior for the offending line, nor even any limits on
    > the possible behaviors.
    >
    >      In particular, there's no guarantee that "you'll get 2 -2."
    >
    >      A particular implementation is free to add (or not) its own
    > definitions to cover cases the Standard leaves undefined -- but
    > then you're no longer talking about "C," but about "Frobozz Magic
    > C Version 4.2 optimization level 3 with #pragma DWIM in effect."
    >
    > > Anyway, writing code
    > > like that is a very bad practice, you can not be sure what's going to
    > > happen in the end :)

    >
    >      Exactly: "What's going to happen" is not defined by the C language.
    >
    > --
    > Eric Sosman
    >


    I have learned the attempting to assign a value to a variable and
    fetching the value of it in the same expression will produce an
    undefined behaviour. What are some of the other cases that produce
    undefined behaviour? This is interesting!

    Thanks!
     
    Mazen, Sep 11, 2011
    #11
  12. Mazen

    Joe Pfeiffer Guest

    Mazen <> writes:

    > Thanks, Eric. So, how can one achieve the desired result and guarantee
    > a defined behavior?


    In short, "don't do that".

    Getting your desired result depends (of course) on what result you
    desired. Assuming your printf() was meant to be

    printf("%d %d\n", i = +j, i = -j);

    (so you were using an unnecessary '+', as opposed to using the old =+
    syntax for += ), then even if it were defined it would be silly. Why
    exactly did you assign a value to i, and then assign another value to
    it?

    If your intent was to print the value of j, print the value of -j, and
    set i to -j, here's something that will do it:

    printf("%d %d\n", j, i = -j);

    If your intent was something else, well, you'd have to do something
    else.
     
    Joe Pfeiffer, Sep 11, 2011
    #12
  13. Mazen

    Joe Pfeiffer Guest

    Mazen <> writes:
    >
    > I have learned the attempting to assign a value to a variable and
    > fetching the value of it in the same expression will produce an
    > undefined behaviour. What are some of the other cases that produce
    > undefined behaviour? This is interesting!


    That isn't what you should have learned, because that's perfectly well
    defined. If your printf() had been

    printf("%d ", i = +j);
    printf("%d\n", i = -j);

    it would have printed the 2 -2 you expected -- though the first
    assignment to i would still have been silly, and doing the second
    assignment in the printf() would still have been useless obfuscation.

    What was undefined was the order in which your three arguments
    to printf() were evaluated, in a context where different orders of
    evaluation would give different results.

    I would be very surprised if anybody actually knows how many ways there
    are to provoke undefined output. I supposed searching the standard for
    the word "undefined" would help, but of course that would only tell you
    all the ways the standard actually says something is undefined, and miss
    all the possible things you could do that just don't have definitions.

    But, frankly, the only reason to want to know what isn't defined is to
    avoid doing it. And "don't write obviously silly code" (like your
    original printf() ) is one of the most basic rules for doing that.
     
    Joe Pfeiffer, Sep 11, 2011
    #13
  14. Mazen <> writes:
    <snip>
    > I have learned the attempting to assign a value to a variable and
    > fetching the value of it in the same expression will produce an
    > undefined behaviour. What are some of the other cases that produce
    > undefined behaviour? This is interesting!


    If that were true, C would not allow:

    x = x + 1;

    The wording 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 read only to
    determine the value to be stored."

    so you may read the value (x) to determine the value to be stored (x +
    1). However, in your case, the problem was modifying the value twice.

    To understand the rule, you have to know where the sequence points are in
    a C program. The standard has a list (edited here for clarity):

    1. The call to a function, after the arguments have been evaluated

    2. The end of the first operand of the following operators: logical
    AND &&; logical OR ||; conditional ?; comma , .

    3. The end of a full declarator: declarators.

    4. The end of a full expression: an initializer; the expression in an
    expression statement; the controlling expression of a selection
    statement (if or switch); the controlling expression of a while or
    do statement; each of the expressions of a for statement; the
    expression in a return statement.

    5. Immediately before a library function returns.

    6. After the actions associated with each formatted input/output
    function conversion specifier.

    7. Immediately before and immediately after each call to a comparison
    function, and also between any call to a comparison function and
    any movement of the objects passed as arguments to that call.

    As has been pointed out, the comma in number 2 is the operator and does
    not appear in a normal function call -- that comma is just syntax for
    the call. Number 7 is about the internals of the qsort and bsearch
    library functions.

    --
    Ben.
     
    Ben Bacarisse, Sep 11, 2011
    #14
  15. On Sep 11, 3:52 am, Joe Pfeiffer <> wrote:
    > Mazen <> writes:
    >
    > > I have learned the attempting to assign a value to a variable and
    > > fetching the value of it in the same expression will produce an
    > > undefined behaviour. What are some of the other cases that produce
    > > undefined behaviour? This is interesting!

    >
    > That isn't what you should have learned, because that's perfectly well
    > defined.  If your printf() had been
    >
    >   printf("%d ", i = +j);
    >   printf("%d\n", i = -j);
    >
    > it would have printed the 2 -2 you expected -- though the first
    > assignment to i would still have been silly, and doing the second
    > assignment in the printf() would still have been useless obfuscation.
    >
    > What was undefined was the order in which your three arguments
    > to printf() were evaluated, in a context where different orders of
    > evaluation would give different results.
    >
    > I would be very surprised if anybody actually knows how many ways there
    > are to provoke undefined output.


    I think there's an appendix in the standard that lists the undefined
    bahaviours


     I supposed searching the standard for
    > the word "undefined" would help, but of course that would only tell you
    > all the ways the standard actually says something is undefined, and miss
    > all the possible things you could do that just don't have definitions.
    >
    > But, frankly, the only reason to want to know what isn't defined is to
    > avoid doing it.  And "don't write obviously silly code" (like your
    > original printf() ) is one of the most basic rules for doing that.
     
    Nick Keighley, Sep 11, 2011
    #15
  16. Mazen

    Eric Sosman Guest

    On 9/10/2011 8:51 PM, Mazen wrote:
    > Thanks, Eric. So, how can one achieve the desired result and guarantee a defined behavior?


    What is the desired result?

    --
    Eric Sosman
    d
     
    Eric Sosman, Sep 11, 2011
    #16
  17. In article <j4idfv$bi5$>,
    Eric Sosman <> wrote:
    >On 9/10/2011 8:51 PM, Mazen wrote:
    >> Thanks, Eric. So, how can one achieve the desired result and guarantee

    >a defined behavior?
    >
    > What is the desired result?


    That was clearly stated in the OP, but I forget it at the moment. I think
    it was "2 2".

    Anyway, the best way to fix the program is to replace the printf() statement
    (and most of the declarations) with:

    puts("2 2");

    --

    Some of the more common characteristics of Asperger syndrome include:

    * Inability to think in abstract ways (eg: puns, jokes, sarcasm, etc)
    * Difficulties in empathising with others
    * Problems with understanding another person's point of view
    * Hampered conversational ability
    * Problems with controlling feelings such as anger, depression
    and anxiety
    * Adherence to routines and schedules, and stress if expected routine
    is disrupted
    * Inability to manage appropriate social conduct
    * Delayed understanding of sexual codes of conduct
    * A narrow field of interests. For example a person with Asperger
    syndrome may focus on learning all there is to know about
    baseball statistics, politics or television shows.
    * Anger and aggression when things do not happen as they want
    * Sensitivity to criticism
    * Eccentricity
    * Behaviour varies from mildly unusual to quite aggressive
    and difficult
     
    Kenny McCormack, Sep 11, 2011
    #17
  18. Mazen

    BartC Guest

    "Mazen" <> wrote in message
    news:...
    > Thanks, Eric. So, how can one achieve the desired result and guarantee a
    > defined behavior?


    Possibly something like:

    printf("%d", i=+j);
    printf(" %d\n", i=-j);

    Or, if you don't care about the value of i at the end (and above, the first
    assignment to i has no purpose):

    printf("%d %d\n", +j, -j);

    would work as well.

    --
    Bartc
     
    BartC, Sep 11, 2011
    #18
  19. Mazen <> writes:
    [...]
    > I have learned the attempting to assign a value to a variable and
    > fetching the value of it in the same expression will produce an
    > undefined behaviour.


    As Joe Pfeiffer points out, that's not quite correct.

    > What are some of the other cases that produce
    > undefined behaviour? This is interesting!


    Grab a copy of the latest C99 draft from

    http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf

    and read section J.2.

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Sep 11, 2011
    #19
  20. Mazen

    James Kuyper Guest

    On 09/11/2011 09:03 AM, Nick Keighley wrote:

    > I think there's an appendix in the standard that lists the undefined
    > bahaviours


    I don't think you said what you meant to say: "undefined behaviors" is a
    category that includes all behaviors; a set far easier to describe than
    to list. :) The list would be of negligible value even if it the list
    could easily be created.

    Annex J.2 does list features that program can have that can cause the
    behavior to be undefined. Note, however, that it cannot be
    all-inclusive. Behavior that is undefined "by omission of any explicit
    definition of behavior" (4p6), is inherently difficult to identify and list.
    --
    James Kuyper
     
    James Kuyper, Sep 11, 2011
    #20
    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. Kyle Kolander

    unexpected stream output with commas

    Kyle Kolander, May 26, 2005, in forum: C++
    Replies:
    10
    Views:
    548
    Kyle Kolander
    May 27, 2005
  2. Evan Carmi

    Unexpected output while walking dirs

    Evan Carmi, Dec 28, 2006, in forum: Python
    Replies:
    2
    Views:
    312
    Evan Carmi
    Jan 2, 2007
  3. Tom Lam lemontea

    Unexpected repeating of my output function

    Tom Lam lemontea, Oct 22, 2004, in forum: C Programming
    Replies:
    5
    Views:
    313
  4. output unexpected

    , Sep 14, 2006, in forum: C Programming
    Replies:
    11
    Views:
    551
    Keith Thompson
    Sep 15, 2006
  5. Sanchit
    Replies:
    8
    Views:
    354
    Keith Thompson
    Mar 22, 2008
Loading...

Share This Page