C Test Incorrectly Uses printf() - Please Confirm

Discussion in 'C Programming' started by Martin O'Brien, Aug 8, 2010.

  1. I took an online C test a few months ago. I actually thought the test
    was better than some I've taken, but one question in particular I
    think has the wrong answer. The question is this:

    What is printed:

    int a = 1;
    printf("%d", ++a, a + 5);

    a. 1
    b. 2
    c. 7
    d. undefined

    I selected d. This is the explanation given as to why b is the correct
    answer.

    The first expression in the parameter list following the format
    string is paired with the first (and only) conversion specification.
    The increment is a prefix so the result of the operation is the a + 1.
    Since there are more items in the value list than there are conversion
    specifications, the extra value is not shown.

    I believe the correct answer is d because according to K&R2 (and by
    implication the Standard) the order in which function arguments are
    evaluated is not defined; in fact, K&R2's example, in Section 2.12,
    shows the variable n being used twice in the same printf call (albeit
    with the correct number of conversion specifications).

    Am I correct that d is the correct answer?

    --
    Martin
     
    Martin O'Brien, Aug 8, 2010
    #1
    1. Advertising

  2. On Aug 8, 9:55 pm, "Martin O'Brien" <> wrote:
    >
    >    int a = 1;
    >    printf("%d", ++a, a + 5);
    >
    >    a. 1
    >    b. 2
    >    c. 7
    >    d. undefined


    > Am I correct that d is the correct answer?
    >

    I'm pretty sure you're right. But the important thing is it doesn't
    really matter. It's not clear what the value of a + 5 should be, or is
    intended by the programmer, so the construct is unusable. It may be
    implementation-defined rather than undefined, but that leads us into
    inappropriate thumbing through the footnotes of the standard, and is
    something only a compiler writer should do.
     
    Malcolm McLean, Aug 8, 2010
    #2
    1. Advertising

  3. Martin O'Brien

    Shao Miller Guest

    Martin O'Brien wrote:
    > I took an online C test a few months ago. I actually thought the test
    > was better than some I've taken, but one question in particular I
    > think has the wrong answer. The question is this:
    >
    > What is printed:
    >
    > int a = 1;
    > printf("%d", ++a, a + 5);
    >
    > a. 1
    > b. 2
    > c. 7
    > d. undefined
    >
    > I selected d. This is the explanation given as to why b is the correct
    > answer.

    What about (b)? There is a sequence point before the function 'printf'
    is called, so '++a' has finished being evaluated and has modified the
    value of 'a'. 'a + 5' is also evaluated, but the format string doesn't
    use that argument. 'a + 5' does not attempt to modify the value of 'a'.
    > ... ... ...
     
    Shao Miller, Aug 8, 2010
    #3
  4. Martin O'Brien

    Shao Miller Guest

    Shao Miller wrote:
    > Martin O'Brien wrote:
    >> I took an online C test a few months ago. I actually thought the test
    >> was better than some I've taken, but one question in particular I
    >> think has the wrong answer. The question is this:
    >>
    >> What is printed:
    >>
    >> int a = 1;
    >> printf("%d", ++a, a + 5);
    >>
    >> a. 1
    >> b. 2
    >> c. 7
    >> d. undefined
    >>
    >> I selected d. This is the explanation given as to why b is the correct
    >> answer.

    > What about (b)? There is a sequence point before the function 'printf'
    > is called, so '++a' has finished being evaluated and has modified the
    > value of 'a'. 'a + 5' is also evaluated, but the format string doesn't
    > use that argument. 'a + 5' does not attempt to modify the value of 'a'.
    >> ... ... ...

    As in, the second argument has a definite value at least by the time of
    the function call. So does the third argument have a value. It doesn't
    matter whether the third argument's value is 6 or 7, because the format
    string doesn't use it. Thus '2' is printed.

    If the question instead asked, "What will be the value passed as the
    third argument?" I would guess (d). But the order in which these
    arguments are evaluated cannot impact what value is passed as the second
    argument; the only one to be printed.
     
    Shao Miller, Aug 8, 2010
    #4
  5. Martin O'Brien

    bert Guest

    On 8 Aug, 19:55, "Martin O'Brien" <> wrote:
    > I took an online C test a few months ago. I actually thought the test
    > was better than some I've taken, but one question in particular I
    > think has the wrong answer. The question is this:
    >
    >    What is printed:
    >
    >    int a = 1;
    >    printf("%d", ++a, a + 5);
    >
    >    a. 1
    >    b. 2
    >    c. 7
    >    d. undefined
    >
    > I selected d. This is the explanation given as to why b is the correct
    > answer.
    >
    >    The first expression in the parameter list following the format
    > string is paired with the first (and only) conversion specification.
    > The increment is a prefix so the result of the operation is the a + 1.
    > Since there are more items in the value list than there are conversion
    > specifications, the extra value is not shown.
    >
    > I believe the correct answer is d because according to K&R2 (and by
    > implication the Standard) the order in which function arguments are
    > evaluated is not defined; in fact, K&R2's example, in Section 2.12,
    > shows the variable n being used twice in the same printf call (albeit
    > with the correct number of conversion specifications).
    >
    > Am I correct that d is the correct answer?
    >
    > --
    > Martin


    No, the correct answer is (b). Answer (d)
    would apply where the printf arguments were
    the other way round.

    The argument "++a" evaluates to 2, whether
    it is evaluated before "a + 5" or after it.

    The argument "a + 5" is likely to evaluate
    to either 6 or 7, depending on whether it is
    evaluated before or after "++a". The standard
    may well allow its evaluation to be undefined,
    because of the ++a (I'm no standards expert)
    but as the argument isn't printed, it doesn't
    matter.

    However: that printf format string does not
    have a new line character, so the output
    will not appear at once; and there have
    been implementations of printf which
    assumed that their parameter count matched
    the number of fields in the format string,
    and caused a stack fault if it didn't; in
    which case the answer would be (e) nothing.
    --
     
    bert, Aug 8, 2010
    #5
  6. On Sun, 8 Aug 2010, Martin O'Brien wrote:

    > I took an online C test a few months ago. I actually thought the test
    > was better than some I've taken, but one question in particular I think
    > has the wrong answer. The question is this:
    >
    > What is printed:
    >
    > int a = 1;
    > printf("%d", ++a, a + 5);
    >
    > a. 1
    > b. 2
    > c. 7
    > d. undefined
    >
    > I selected d. This is the explanation given as to why b is the correct
    > answer.
    >
    > The first expression in the parameter list following the format string
    > is paired with the first (and only) conversion specification. The
    > increment is a prefix so the result of the operation is the a + 1. Since
    > there are more items in the value list than there are conversion
    > specifications, the extra value is not shown.
    >
    > I believe the correct answer is d because according to K&R2 (and by
    > implication the Standard) the order in which function arguments are
    > evaluated is not defined; in fact, K&R2's example, in Section 2.12,
    > shows the variable n being used twice in the same printf call (albeit
    > with the correct number of conversion specifications).
    >
    > Am I correct that d is the correct answer?


    Yes, but I believe not for the reason you mention.

    C99 6.5.2.2 Function calls, p10:

    "The order of evaluation of the function designator, the actual arguments,
    and subexpressions within the actual arguments is unspecified, but there
    is a sequence point before the actual call."

    So the order of evaluation is unspecified, not undefined. However,

    C99 6.5 Expressions, p2:

    "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."

    Here are the sequence points:

    > int a = 1;


    SP#1 at semicolon.

    > printf(
    > "%d", ++a, a + 5


    SP#2 after "printf" (the function designator) and all arguments have been
    evaluated (in unspecified order), right before printf() is entered.

    > );


    SP#3 at semicolon.

    "a" is read twice and written once between SP#1 and SP#2. The expression
    "a+5" reads "a" *not* in order to determine "a"'s next value, so 6.5p2 is
    violated. Hence the undefined behavior.

    (In practice, compilers need 6.5p2 so that they can reliably order
    store/load operations between adjacent sequence points along data
    dependency edges. If no such dependency is found, they can choose whatever
    order. They can even overlap/interleave such simple expressions as ++a and
    a+5 -- not function calls though.)

    Under this aspect, it is irrelevant that the value of a+5 will be "thrown
    away" anyway. C's eval is eager (see 6.5.2.2p10 above, for example), not
    lazy.

    lacos

    --
    All content in this message, posted from <>, is my
    personal opinion, representing noone else than myself.
     
    Ersek, Laszlo, Aug 8, 2010
    #6
  7. Martin O'Brien

    Eric Sosman Guest

    On 8/8/2010 2:55 PM, Martin O'Brien wrote:
    > I took an online C test a few months ago. I actually thought the test
    > was better than some I've taken, but one question in particular I
    > think has the wrong answer. The question is this:
    >
    > What is printed:
    >
    > int a = 1;
    > printf("%d", ++a, a + 5);
    >
    > a. 1
    > b. 2
    > c. 7
    > d. undefined
    >
    > I selected d. This is the explanation given as to why b is the correct
    > answer.


    You were right.

    > The first expression in the parameter list following the format
    > string is paired with the first (and only) conversion specification.
    > The increment is a prefix so the result of the operation is the a + 1.
    > Since there are more items in the value list than there are conversion
    > specifications, the extra value is not shown.


    The explanation is wrong. The undefined behavior arises from the
    lack of a sequence point between ++a and a+5, before printf() even
    begins to execute. It doesn't matter that the value (if any) of a+5
    won't be used; the behavior is undefined anyhow.

    Ponder this one:

    printf ("%d\n", ++a, strlen(NULL));

    The fact that the printf() will not use its third parameter does not
    mean that the third argument's undefined behavior is forgiven.

    > I believe the correct answer is d because according to K&R2 (and by
    > implication the Standard) the order in which function arguments are
    > evaluated is not defined; in fact, K&R2's example, in Section 2.12,
    > shows the variable n being used twice in the same printf call (albeit
    > with the correct number of conversion specifications).
    >
    > Am I correct that d is the correct answer?


    Yes.

    --
    Eric Sosman
    lid
     
    Eric Sosman, Aug 8, 2010
    #7
  8. Martin O'Brien

    Willem Guest

    Shao Miller wrote:
    ) As in, the second argument has a definite value at least by the time of
    ) the function call. So does the third argument have a value. It doesn't
    ) matter whether the third argument's value is 6 or 7, because the format
    ) string doesn't use it. Thus '2' is printed.

    It's undefined behaviour. Anything can happen.
    '2' is not *guaranteed*.

    I agree, it's extremely unlikely to be anything else.
    Probably no system exists where it would not print 2.
    But pedantically speaking, the result *is* undefined.

    But in some theoretical machine, it could fail.
    (For example, the instructions for reading in a+5 and writing in a++
    could be parallelized into the same slot, and the simultaneous read
    and write could cause some kind of signal to be raised.)


    SaSW, Willem
    --
    Disclaimer: I am in no way responsible for any of the statements
    made in the above text. For all I know I might be
    drugged or something..
    No I'm not paranoid. You all think I'm paranoid, don't you !
    #EOT
     
    Willem, Aug 8, 2010
    #8
  9. Malcolm McLean <> writes:
    > On Aug 8, 9:55 pm, "Martin O'Brien" <> wrote:
    >>    int a = 1;
    >>    printf("%d", ++a, a + 5);
    >>
    >>    a. 1
    >>    b. 2
    >>    c. 7
    >>    d. undefined

    >
    >> Am I correct that d is the correct answer?
    >>

    > I'm pretty sure you're right. But the important thing is it doesn't
    > really matter. It's not clear what the value of a + 5 should be, or is
    > intended by the programmer, so the construct is unusable. It may be
    > implementation-defined rather than undefined, but that leads us into
    > inappropriate thumbing through the footnotes of the standard, and is
    > something only a compiler writer should do.


    The standard is not intended only for compiler writers. It is, in
    effect, a contract between implementers and programmers; as such,
    both implementers and programmers can benefit from being familiar
    with it.

    In practice, the fact that the presented code is ugly and should
    never pass a code review, whether its behavior is defined or not,
    may be more important than the reasons why its behavior is undefined.
    But I'd be interested in knowing why you think that reading the
    standard (and no, footnotes aren't relevant here) is "something
    only a compiler writer should do.".

    --
    Keith Thompson (The_Other_Keith) <http://www.ghoti.net/~kst>
    Nokia
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"
     
    Keith Thompson, Aug 8, 2010
    #9
  10. Martin O'Brien

    Shao Miller Guest

    Ersek, Laszlo wrote:
    > On Sun, 8 Aug 2010, Martin O'Brien wrote:
    >
    >> I took an online C test a few months ago. I actually thought the test
    >> was better than some I've taken, but one question in particular I
    >> think has the wrong answer. The question is this:
    >>
    >> What is printed:
    >>
    >> int a = 1;
    >> printf("%d", ++a, a + 5);
    >>
    >> a. 1
    >> b. 2
    >> c. 7
    >> d. undefined
    >>
    >> I selected d. This is the explanation given as to why b is the correct
    >> answer.
    >>
    >> The first expression in the parameter list following the format
    >> string is paired with the first (and only) conversion specification.
    >> The increment is a prefix so the result of the operation is the a + 1.
    >> Since there are more items in the value list than there are conversion
    >> specifications, the extra value is not shown.
    >>
    >> I believe the correct answer is d because according to K&R2 (and by
    >> implication the Standard) the order in which function arguments are
    >> evaluated is not defined; in fact, K&R2's example, in Section 2.12,
    >> shows the variable n being used twice in the same printf call (albeit
    >> with the correct number of conversion specifications).
    >>
    >> Am I correct that d is the correct answer?

    >
    > Yes, but I believe not for the reason you mention.
    >
    > C99 6.5.2.2 Function calls, p10:
    >
    > "The order of evaluation of the function designator, the actual
    > arguments, and subexpressions within the actual arguments is
    > unspecified, but there is a sequence point before the actual call."
    >
    > So the order of evaluation is unspecified, not undefined. However,
    >
    > C99 6.5 Expressions, p2:
    >
    > "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."
    >
    > Here are the sequence points:
    >
    >> int a = 1;

    >
    > SP#1 at semicolon.
    >
    >> printf(
    >> "%d", ++a, a + 5

    >
    > SP#2 after "printf" (the function designator) and all arguments have
    > been evaluated (in unspecified order), right before printf() is entered.
    >
    >> );

    >
    > SP#3 at semicolon.
    >
    > "a" is read twice and written once between SP#1 and SP#2. The expression
    > "a+5" reads "a" *not* in order to determine "a"'s next value, so 6.5p2
    > is violated. Hence the undefined behavior.
    >
    > (In practice, compilers need 6.5p2 so that they can reliably order
    > store/load operations between adjacent sequence points along data
    > dependency edges. If no such dependency is found, they can choose
    > whatever order. They can even overlap/interleave such simple expressions
    > as ++a and a+5 -- not function calls though.)
    >
    > Under this aspect, it is irrelevant that the value of a+5 will be
    > "thrown away" anyway. C's eval is eager (see 6.5.2.2p10 above, for
    > example), not lazy.

    Whoa. It never occurred to me that:

    int i = 1;
    i = i + i;

    could yield undefined behaviour due to the double-read and the single
    store. Amazing! Nice one! Instead, we should use:

    int i = 1;
    i += i;

    Because it differs from:

    int i = 1;
    i = i + i;

    In that with the similarity between 'E1 += E2' and 'E1 = E1 + E2' in the
    latter case, 'E1' is only evaluated once. But uh oh... What about 'E2'?

    I suppose the only well-behaved way to do it is:

    int i = 1, j;
    j = i;
    i = i + j;

    Is that right?
     
    Shao Miller, Aug 8, 2010
    #10
  11. Martin O'Brien

    Shao Miller Guest

    Shao Miller wrote:
    > I suppose the only well-behaved way to do it is:
    >
    > int i = 1, j;
    > j = i;
    > i = i + j;
    >
    > Is that right?

    Or:

    int i = 1;
    i = i * 2;

    (Of course.)
     
    Shao Miller, Aug 8, 2010
    #11
  12. Martin O'Brien

    Shao Miller Guest

    Willem wrote:
    > Shao Miller wrote:
    > ) As in, the second argument has a definite value at least by the time of
    > ) the function call. So does the third argument have a value. It doesn't
    > ) matter whether the third argument's value is 6 or 7, because the format
    > ) string doesn't use it. Thus '2' is printed.
    >
    > It's undefined behaviour. Anything can happen.
    > '2' is not *guaranteed*.
    >
    > I agree, it's extremely unlikely to be anything else.
    > Probably no system exists where it would not print 2.
    > But pedantically speaking, the result *is* undefined.
    >
    > But in some theoretical machine, it could fail.
    > (For example, the instructions for reading in a+5 and writing in a++
    > could be parallelized into the same slot, and the simultaneous read
    > and write could cause some kind of signal to be raised.)

    What makes it undefined behaviour, if you please?

    Is it also undefined behaviour for:

    int i = 1;
    i = i + i;

    ?
     
    Shao Miller, Aug 8, 2010
    #12
  13. Martin O'Brien

    Eric Sosman Guest

    On 8/8/2010 4:47 PM, Shao Miller wrote:
    > Willem wrote:
    >> Shao Miller wrote:
    >> ) As in, the second argument has a definite value at least by the time
    >> of ) the function call. So does the third argument have a value. It
    >> doesn't ) matter whether the third argument's value is 6 or 7, because
    >> the format ) string doesn't use it. Thus '2' is printed.
    >>
    >> It's undefined behaviour. Anything can happen.
    >> '2' is not *guaranteed*.
    >>
    >> I agree, it's extremely unlikely to be anything else.
    >> Probably no system exists where it would not print 2.
    >> But pedantically speaking, the result *is* undefined.
    >>
    >> But in some theoretical machine, it could fail.
    >> (For example, the instructions for reading in a+5 and writing in a++
    >> could be parallelized into the same slot, and the simultaneous read
    >> and write could cause some kind of signal to be raised.)

    > What makes it undefined behaviour, if you please?


    `++a, a+5' with no sequence point to separate them. 6.5p2:

    "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."

    .... with special attention to the second sentence. `++a' reads the
    value once to determine the value stored, and `a+5' reads the value
    for a different purpose. U.B.

    > Is it also undefined behaviour for:
    >
    > int i = 1;
    > i = i + i;


    No. The Standard says "shall be read," not "shall be read
    exactly once."

    --
    Eric Sosman
    lid
     
    Eric Sosman, Aug 8, 2010
    #13
  14. Martin O'Brien

    Shao Miller Guest

    Eric Sosman wrote:
    > On 8/8/2010 2:55 PM, Martin O'Brien wrote:
    >> I took an online C test a few months ago. I actually thought the test
    >> was better than some I've taken, but one question in particular I
    >> think has the wrong answer. The question is this:
    >>
    >> What is printed:
    >>
    >> int a = 1;
    >> printf("%d", ++a, a + 5);
    >>
    >> ... ... ...

    >
    > Ponder this one:
    >
    > printf ("%d\n", ++a, strlen(NULL));
    >
    > The fact that the printf() will not use its third parameter does not
    > mean that the third argument's undefined behavior is forgiven.

    I'm not sure I'd agree to pondering this example for similarity to the
    first. There are two additional sequence points here; one before the
    call to 'strlen' and one immediate before 'strlen' returns. Thus there
    is more opportunity for undefined behaviour than in the original. Would
    you agree?

    5.1.2.3,p2 (of 'n1256.pdf'):

    "...At certain specified points in the execution sequence called
    sequence points, all side effects of previous evaluations shall be
    complete and no side effects of subsequent evaluations shall have taken
    place."
     
    Shao Miller, Aug 8, 2010
    #14
  15. Martin O'Brien

    Eric Sosman Guest

    On 8/8/2010 5:17 PM, Shao Miller wrote:
    > Eric Sosman wrote:
    >> On 8/8/2010 2:55 PM, Martin O'Brien wrote:
    >>> I took an online C test a few months ago. I actually thought the test
    >>> was better than some I've taken, but one question in particular I
    >>> think has the wrong answer. The question is this:
    >>>
    >>> What is printed:
    >>>
    >>> int a = 1;
    >>> printf("%d", ++a, a + 5);
    >>>
    >>> ... ... ...

    >>
    >> Ponder this one:
    >>
    >> printf ("%d\n", ++a, strlen(NULL));
    >>
    >> The fact that the printf() will not use its third parameter does not
    >> mean that the third argument's undefined behavior is forgiven.

    > I'm not sure I'd agree to pondering this example for similarity to the
    > first. There are two additional sequence points here; one before the
    > call to 'strlen' and one immediate before 'strlen' returns. Thus there
    > is more opportunity for undefined behaviour than in the original. Would
    > you agree?


    (Shrug.) If that worries you, consider

    printf ("%d\n", ++a, *(char*)NULL);

    --
    Eric Sosman
    lid
     
    Eric Sosman, Aug 8, 2010
    #15
  16. Martin O'Brien

    Shao Miller Guest

    Eric Sosman wrote:
    > On 8/8/2010 4:47 PM, Shao Miller wrote:
    >> Willem wrote:
    >>> Shao Miller wrote:
    >>> ) As in, the second argument has a definite value at least by the time
    >>> of ) the function call. So does the third argument have a value. It
    >>> doesn't ) matter whether the third argument's value is 6 or 7, because
    >>> the format ) string doesn't use it. Thus '2' is printed.
    >>>
    >>> It's undefined behaviour. Anything can happen.
    >>> '2' is not *guaranteed*.
    >>>
    >>> I agree, it's extremely unlikely to be anything else.
    >>> Probably no system exists where it would not print 2.
    >>> But pedantically speaking, the result *is* undefined.
    >>>
    >>> But in some theoretical machine, it could fail.
    >>> (For example, the instructions for reading in a+5 and writing in a++
    >>> could be parallelized into the same slot, and the simultaneous read
    >>> and write could cause some kind of signal to be raised.)

    >> What makes it undefined behaviour, if you please?

    >
    > `++a, a+5' with no sequence point to separate them. 6.5p2:
    >
    > "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."
    >
    > ... with special attention to the second sentence. `++a' reads the
    > value once to determine the value stored, and `a+5' reads the value
    > for a different purpose. U.B.

    Thanks, Eric. :)

    >> Is it also undefined behaviour for:
    >>
    >> int i = 1;
    >> i = i + i;

    >
    > No. The Standard says "shall be read," not "shall be read
    > exactly once."
    >

    I think I understand. So in:

    int i = 1, j;
    i = j = i + i * 9 + 3;

    we are likewise protected because we can conclude that sooner or later
    within some expression, we are modifying the stored value of 'i'. Is
    that right?
     
    Shao Miller, Aug 8, 2010
    #16
  17. On Sun, 8 Aug 2010 11:55:26 -0700 (PDT), "Martin O'Brien"
    <> wrote:

    >I took an online C test a few months ago. I actually thought the test
    >was better than some I've taken, but one question in particular I
    >think has the wrong answer. The question is this:
    >
    > What is printed:
    >
    > int a = 1;
    > printf("%d", ++a, a + 5);
    >
    > a. 1
    > b. 2
    > c. 7
    > d. undefined
    >
    >I selected d. This is the explanation given as to why b is the correct
    >answer.
    >
    > The first expression in the parameter list following the format
    >string is paired with the first (and only) conversion specification.
    >The increment is a prefix so the result of the operation is the a + 1.
    >Since there are more items in the value list than there are conversion
    >specifications, the extra value is not shown.
    >
    >I believe the correct answer is d because according to K&R2 (and by
    >implication the Standard) the order in which function arguments are
    >evaluated is not defined; in fact, K&R2's example, in Section 2.12,
    >shows the variable n being used twice in the same printf call (albeit
    >with the correct number of conversion specifications).
    >
    >Am I correct that d is the correct answer?


    I think so, due to violating 6.5-2.

    There is a sequence point prior to the start of the printf statement.
    The next sequence pint is when printf is called. Between the two, the
    arguments are evaluated. As a result of evaluating the second
    argument, the value stored in object a is modified, we just don't know
    exactly when. Evaluating the third argument reads the value of object
    a for a purpose other than determining what the new value should be.

    The fact that the third argument is never used probably eliminates the
    practical impact of the undefined behavior. (I wonder if there are
    any systems other than the DS9000 which would fail to do the
    expected.) But that does not change the fact that a shall constraint
    has been violated.

    --
    Remove del for email
     
    Barry Schwarz, Aug 8, 2010
    #17
  18. Martin O'Brien

    Shao Miller Guest

    Barry Schwarz wrote:
    > On Sun, 8 Aug 2010 11:55:26 -0700 (PDT), "Martin O'Brien"
    > <> wrote:
    >
    >> I took an online C test a few months ago. I actually thought the test
    >> was better than some I've taken, but one question in particular I
    >> think has the wrong answer. The question is this:
    >>
    >> What is printed:
    >>
    >> int a = 1;
    >> printf("%d", ++a, a + 5);
    >>
    >> a. 1
    >> b. 2
    >> c. 7
    >> d. undefined
    >>
    >> I selected d. This is the explanation given as to why b is the correct
    >> answer.
    >>
    >> The first expression in the parameter list following the format
    >> string is paired with the first (and only) conversion specification.
    >> The increment is a prefix so the result of the operation is the a + 1.
    >> Since there are more items in the value list than there are conversion
    >> specifications, the extra value is not shown.
    >>
    >> I believe the correct answer is d because according to K&R2 (and by
    >> implication the Standard) the order in which function arguments are
    >> evaluated is not defined; in fact, K&R2's example, in Section 2.12,
    >> shows the variable n being used twice in the same printf call (albeit
    >> with the correct number of conversion specifications).
    >>
    >> Am I correct that d is the correct answer?

    >
    > I think so, due to violating 6.5-2.

    I disagree.
    >
    > There is a sequence point prior to the start of the printf statement.
    > The next sequence pint is when printf is called. Between the two, the
    > arguments are evaluated.

    Agreed.

    > As a result of evaluating the second
    > argument, the value stored in object a is modified, we just don't know
    > exactly when.

    I disagree. 5.1.2.3,p2:

    "...At certain specified points in the execution sequence called
    sequence points, all side effects of previous evaluations shall be
    complete and no side effects of subsequent evaluations shall have taken
    place."

    The object designated by 'a' has its stored value modified not before
    the sequence point just before calling the function. The side effects
    are effectively coalesced at that point in time, by this definition.

    > Evaluating the third argument reads the value of object
    > a for a purpose other than determining what the new value should be.
    >

    The argument list in a function call is a comma-separated list of
    expressions to be evaluated, not a single expression (the syntax of
    6.5.2,p1 and the semantics of 6.5.2.2,p3). 6.5,p2 states "an
    expression" rather than "an expression or a comma-separated list of
    expressions".

    > The fact that the third argument is never used probably eliminates the
    > practical impact of the undefined behavior.

    I do not agree that there is no undefined behaviour. I believe that the
    correct answer is (b).

    > (I wonder if there are
    > any systems other than the DS9000 which would fail to do the
    > expected.) But that does not change the fact that a shall constraint
    > has been violated.
    >

    The value of 'a' is stable between its initializing declaration and the
    instant before 'printf' is called. No single expression attempts to
    modify the value and read the value for some other purpose. Would you
    agree?
     
    Shao Miller, Aug 8, 2010
    #18
  19. Martin O'Brien

    Shao Miller Guest

    Shao Miller wrote:
    > I do not agree that there is no undefined behaviour. I believe that the
    > correct answer is (b).

    Please forgive the typo. That should have been typed as:

    I do not agree that there is undefined behaviour. I believe that the
    correct answer is (b).
     
    Shao Miller, Aug 8, 2010
    #19
  20. Martin O'Brien

    Shao Miller Guest

    pete wrote:
    > Shao Miller wrote:
    >> Ersek, Laszlo wrote:

    >
    >>> Furthermore,
    >>> the prior value shall be read only to determine the value
    >>> to be stored.

    >
    >> Whoa. It never occurred to me that:
    >>
    >> int i = 1;
    >> i = i + i;
    >>
    >> could yield undefined behaviour

    >
    > That's good that it didn't occur to you.
    >
    > The part that Ersek, Laszlo wrote which I didn't snip,
    > applies to that situation.
    >
    > Here's the footnote that goes with it.
    >
    > N869
    > 60)This paragraph renders undefined statement expressions
    > such as
    > i = ++i + 1;
    > a[i++] = i;
    > while allowing
    > i = i + 1;
    > a = i;
    >

    Yes, a good (albeit, non-normative) footnote to think about.

    i = ++i + 1;

    At the sequence point, we have two modification accesses pending for 'i'
    at the same time. Oops! The value of 'i' is guaranteed intact until
    that sequence point.

    a[i++] = i;

    Is defined to be equivalent to:

    (*((a) + (i++))) = i;

    At the sequence point, we have a modification access pending for the
    object designated by '(*((a) + (i++)))' and we have a modification
    access pending for 'i' at the same time. Both of these accesses are
    uses of the value of 'i' in a single expression. Since only one of the
    modification accesses is for 'i', this could be considered as the prior
    value being read for more than just the purpose of determining the value
    to be stored in 'i'.

    i = i + 1;

    At the sequence point, we have a modification access pending for 'i' and
    this is a use of the prior value of 'i'. Eric has suggested that more
    than one read of 'i' is allowed, which would satisfy 'i = i + i;'.

    a = i;

    Is defined to be equivalent to:

    (*((a) + (i))) = i;

    At the sequence point, we have a modification access pending for the
    object designated by '(*((a) + (i)))'. There is no modification access
    pending for 'i', so we can read the value of 'i' as many times as we like.

    So how about here?:

    int i = 1, j;
    i = j = i + i + 1;

    At the sequence point just before the second semi-colon, we have a
    modification access pending for 'i' and a modification access pending
    for 'j'. Is the value of 'i' read for more than one purpose here?

    Thanks, pete. :)
     
    Shao Miller, Aug 9, 2010
    #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. ben
    Replies:
    4
    Views:
    663
    Martin Ambuhl
    Jun 26, 2004
  2. Martin
    Replies:
    4
    Views:
    319
    Ben Bacarisse
    Aug 10, 2010
  3. S.Sigal
    Replies:
    0
    Views:
    147
    S.Sigal
    Aug 14, 2004
  4. S.Sigal
    Replies:
    0
    Views:
    134
    S.Sigal
    Aug 14, 2004
  5. 1gor
    Replies:
    2
    Views:
    349
Loading...

Share This Page