Sequence point.

Discussion in 'C Programming' started by somenath, Sep 30, 2013.

  1. somenath

    somenath Guest

    I am not able to understand why the following program output as follows.

    #include<stdio.h>
    void test(int x,int y)
    {
    printf("x = %d\n",x);
    printf("y = %d\n",y);

    }


    int main(void)
    {
    int i =5;
    int j =5;
    test(++i,j++);

    return 0;
    }

    $ ./a.exe
    x = 6
    y = 5

    According to my understanding function call provide sequence point i.e all the side effect will be guaranteed to be complete ( after the evaluation of all the arguments, and just before the actual cal).
    so in case of j++ the value of the expression is j but as a side effect j gets incremented by 1. So test will receive the value 6,6.
    Where am I going wrong here ?
     
    somenath, Sep 30, 2013
    #1
    1. Advertisements

  2. somenath

    Eric Sosman Guest

    The test() function prints the values x,y -- not the values i,j.
    The expression `++i' adds 1 to `i' and yields the new value; that is
    the value that `x' receives. The expression `j++' adds 1 to `j' and
    yields the original value; that original value is what `y' receives.
    At the point of the printf() calls, then, `x' is 6 and `y' is 5. As
    it happens, both `i' and `j' are now 6, but they're not what test()
    prints.

    Try this modified program; perhaps it will help you understand:

    #include <stdio.h>
    int i = 5; // formerly in main(), now at file scope
    int j = 5; // ditto

    void test(int x, int y) {
    printf("x = %d, y = %d\n", x, y);
    printf("i = %d, j = %d\n", i, j);
    }

    int main(void) {
    test(++i, j++);
    return 0;
    }
     
    Eric Sosman, Sep 30, 2013
    #2
    1. Advertisements

  3. From http://en.cppreference.com/w/cpp/language/operator_incdec :

    pre-increment and pre-decrement operators increments or decrements the value of the object and returns a reference to the result.

    post-increment and post-decrement creates a copy of the object, increments or decrements the value of the object and returns the copy from before the increment or decrement.

    So when you type `j++`, the compiler interprets that as: create a copy of j, then increment the original j, and then pass in the value of the copy to the function. These are the 'side effects' you allude to, and they do indeed all complete before the function call. This is the easiest way to get as close as possible to our intuition - that j++ means 'do all the things toj, and then increment j'.

    It would also be a lot less useful if test(i, j++) and test(i, ++j) did thesame thing.
     
    williamjohn.gowers, Sep 30, 2013
    #3
  4. somenath

    Eric Sosman Guest

    ^^^ ^^^

    Wrong language. C and C++ are not the same.
    No: Both operators yield the *value* (pre- or post-) of the object.
    Neither yields a reference; C does not have references.
    No: Neither operator copies an object, nor does either yield
    a copied object.
    Here, you're right.
     
    Eric Sosman, Sep 30, 2013
    #4
  5. somenath

    James Kuyper Guest

    Not to disagree with you, but simply to clarify:
    Even though C and C++ are not, in general, the same, and even though C
    does not have references, both languages handle the relevant aspects of
    ++ and -- the same.
    C++ operator overloads for those operators are typically written in the
    manner he describes, and C++ handles overload resolution using the
    concept of operator overload functions for built-in type which have the
    same type of function signature. However, those functions don't have to
    actually exist, the concept that they do is just a convenient way to
    organize overload resolution so it handles built-in types in a way
    that's consistent with the way it handles user-defined types. The
    description of how the increment and decrement operators actually work
    for built-in types is very similar to the corresponding section of the C
    standard, and makes no mention of those overloads.
     
    James Kuyper, Sep 30, 2013
    #5
  6. somenath

    somenath Guest

    Thanks for the explanation. I missed the point that the value of the argument is passed to the function.

    So the value of the expression j++ is 5 but the value of j is 6 and the value of the expression that is 5 is passed to the function.
     
    somenath, Sep 30, 2013
    #6
  7. The ++ operator is a bit confusing.

    In most of mathematics, precedence refers to binding as well as to order
    of application. So if we say x = 1 + 2 *3, we apply the 2*3 first, yielding
    six, then add one to it, to give 7.
    However if in C we write int i = 3; x = 1 + 2 *i++; then the ++ is applied to
    the i only, but only after everything else has been evaluated. So x is still
    7, but i is 4.
    It's a little quirk that takes a bit of getting used to, but in fact it makes
    programs easier to write.
     
    Malcolm McLean, Sep 30, 2013
    #7
  8. somenath

    Eric Sosman Guest

    Right. One tiny elaboration: The value of `j' *after the
    sequence point* is 6.
     
    Eric Sosman, Sep 30, 2013
    #8
  9. somenath

    Seebs Guest

    Looks right to me.
    You are misunderstanding "j++". The value of the expression is not "the
    variable j", it is "the value the variable j had before this operator came
    into play".

    Imagine it as being roughly like this:

    int postinc(int *x) {
    int old = *x;
    *x = *x + 1;
    return old;
    }
    int preinc(int *x) {
    int new;
    *x = *x + 1;
    new = *x;
    return new;
    }

    The value "old" in the postinc function isn't going to change it's value just
    because you *later* modified *x.

    The entire point of postincrement is to yield the value j *used to have*. If
    sequence points changed its behavior, it would be useless.

    -s
     
    Seebs, Oct 1, 2013
    #9
  10. somenath

    Seebs Guest

    I don't think it's true that it's "only after everything else has
    been evaluated". The compiler is welcome to, if it really wants,
    increment i before it does anything else in the expression, as long
    as it still uses the value 3.

    Order of evaluation and binding are logically distinct in C. If you write:
    a() + b() * c()
    the compiler is welcome to emit the three function calls in any order, as
    long as the result is computed by multiplying the results of b and c together,
    then adding that to the result of a.

    -s
     
    Seebs, Oct 1, 2013
    #10
  11. Right.

    The expression `j++` *could* be implemented as the equivalent of
    (j = j + 1, j - 1). The side effect of incrementing j can occur
    any time between the previous and next sequence point, as long as
    the value yielded by j++ is as specified.
     
    Keith Thompson, Oct 1, 2013
    #11
    1. Advertisements

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.