Connecting Tech Pros Worldwide Help | Site Map

Knowing your sequence points

akarl
Guest
 
Posts: n/a
#1: Nov 15 '05
Hi all,

Why do I get a warning from gcc with the following program?

[test]$ cat test.c
#include <stdio.h>

int f(int n)
{
return n;
}


int main(void)
{
int n = 0;

printf("%i\n", f(n++) + n);
return 0;
}

[test]$ gcc -Wall test.c
test.c: In function ‘main’:
test.c:13: warning: operation on ‘n’ may be undefined

One of the sequence point cases is defined as: "The point of calling a
function, after evaluating its arguments." If I got it right, that rule
can be applied to `f(n++)' which is evaluated before `n' since addition
is left associative. I can't see the ambiguity here.


August

(I would never write this kind of code in practice, but it's good to
know how the standard is defined.)
pete
Guest
 
Posts: n/a
#2: Nov 15 '05

re: Knowing your sequence points


akarl wrote:[color=blue]
>
> Hi all,
>
> Why do I get a warning from gcc with the following program?
>
> [test]$ cat test.c
> #include <stdio.h>
>
> int f(int n)
> {
> return n;
> }
>
> int main(void)
> {
> int n = 0;
>
> printf("%i\n", f(n++) + n);
> return 0;
> }
>
> [test]$ gcc -Wall test.c
> test.c: In function ‘main’:
> test.c:13: warning: operation on ‘n’ may be undefined
>
> One of the sequence point cases is defined as: "The point of calling a
> function, after evaluating its arguments."
> If I got it right, that rule
> can be applied to `f(n++)' which is evaluated before
> `n' since addition is left associative.
> I can't see the ambiguity here.[/color]

That's not what left associative means.

--
pete
akarl
Guest
 
Posts: n/a
#3: Nov 15 '05

re: Knowing your sequence points


pete wrote:[color=blue]
> akarl wrote:
>[color=green]
>>Hi all,
>>
>>Why do I get a warning from gcc with the following program?
>>
>>[test]$ cat test.c
>>#include <stdio.h>
>>
>>int f(int n)
>>{
>> return n;
>>}
>>
>>int main(void)
>>{
>> int n = 0;
>>
>> printf("%i\n", f(n++) + n);
>> return 0;
>>}
>>
>>[test]$ gcc -Wall test.c
>>test.c: In function ‘main’:
>>test.c:13: warning: operation on ‘n’ may be undefined
>>
>>One of the sequence point cases is defined as: "The point of calling a
>>function, after evaluating its arguments."
>>If I got it right, that rule
>>can be applied to `f(n++)' which is evaluated before
>>`n' since addition is left associative.
>>I can't see the ambiguity here.[/color]
>
>
> That's not what left associative means.[/color]

Yes, of course (only one addition operation). How stupid of me. So the
ambiguity here is that the *evaluation order* of the operands of `+' is
unspecified, right?

August
Jack Klein
Guest
 
Posts: n/a
#4: Nov 15 '05

re: Knowing your sequence points


On Thu, 11 Aug 2005 02:15:14 GMT, akarl <fusionfive@comhem.se> wrote
in comp.lang.c:
[color=blue]
> Hi all,
>
> Why do I get a warning from gcc with the following program?
>
> [test]$ cat test.c
> #include <stdio.h>
>
> int f(int n)
> {
> return n;
> }
>
>
> int main(void)
> {
> int n = 0;
>
> printf("%i\n", f(n++) + n);
> return 0;
> }
>
> [test]$ gcc -Wall test.c
> test.c: In function ‘main’:
> test.c:13: warning: operation on ‘n’ may be undefined[/color]

Yes, the operation on 'n' may be undefined. The standard says:

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

The printf() call in your call does not modify the value of 'n' more
than once. The expression 'n++' modifies 'n' exactly once, and uses
the original value of 'n' only for the purpose of computing the new
value. But the '+ n' subexpression attempts to access the prior value
of 'n' in a way that is not used in the computation of the new value.
[color=blue]
> One of the sequence point cases is defined as: "The point of calling a
> function, after evaluating its arguments." If I got it right, that rule
> can be applied to `f(n++)' which is evaluated before `n' since addition
> is left associative. I can't see the ambiguity here.[/color]

No, you are wrong, associatively has nothing at all to do with order
of evaluation. Only sequence points impose an order of evaluation.
[color=blue]
> August
>
> (I would never write this kind of code in practice, but it's good to
> know how the standard is defined.)[/color]

Let's take an example that doesn't have undefined behavior:

#include <stdio.h>

int f1(void)
{
puts("function 1\n");
return 1;
}

int f2(void)
{
puts("function 1\n");
return 2;
}

int main(void)
{
printf("the sum is %d\n", f1() + f2());
return 0;
}

This function does not define or contain any objects at all, so the
paragraph I quoted from the standard certainly does not apply.

Because the order of evaluation between sequence points is
unspecified, the output could be either of the following two
sequences, and must be one of the two:

function 1
function 2
the sum is 3

....or:

function 2
function 1
the sum is 3

In fact, it may change between one and the other if you change the
settings you use to invoke your compiler, for example enable or
disable optimization.

If just so happens that if your compiler evaluates the subexpression
'f(n++)' first, the result is defined because there is a sequence
point imposed by calling the function before the '+ n' subexpression
reads the value of 'n' again.

But if your compiler evaluates 'n' in the '+ n' subexpression before
evaluating the 'f(n++)' subexpression, there is no sequence point
between the unrelated read and the modification, the behavior is
undefined.

Finally, since the order of evaluation is something the standard
states is unspecified, it means that the compiler does not have to
tell you which order it uses, and is free to change it based on
settings, the day of the week, or the phase of the moon.

Since one of the unspecified paths generates undefined behavior, the
whole thing should be treated as undefined.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
pete
Guest
 
Posts: n/a
#5: Nov 15 '05

re: Knowing your sequence points


akarl wrote:[color=blue]
>
> pete wrote:[color=green]
> > akarl wrote:[/color][/color]
[color=blue][color=green][color=darkred]
> >> printf("%i\n", f(n++) + n);[/color][/color][/color]
[color=blue][color=green][color=darkred]
> >>test.c:13: warning: operation on ‘n’ may be undefined[/color][/color][/color]
[color=blue][color=green][color=darkred]
> >>`f(n++)' which is evaluated before
> >>`n' since addition is left associative.
> >>I can't see the ambiguity here.[/color]
> >
> >
> > That's not what left associative means.[/color]
>
> Yes, of course (only one addition operation). How stupid of me. So the
> ambiguity here is that the *evaluation order*
> of the operands of `+' is unspecified, right?[/color]

Yes. There are rules that say that modifying n
and reading n between sequence points, is undefined,
even though it might seem to be only unspecified.

I think it's good to avoid side effects in function arguments.
I absentmindedly used an argument with side effects in the
Re: A question on string literals
thread, thereby confusing Default User.
It would have been more better if I had
incremented the pointer prior to the function call
instead of in the function call.

--
pete
Martin Ambuhl
Guest
 
Posts: n/a
#6: Nov 15 '05

re: Knowing your sequence points


akarl wrote:[color=blue]
> Hi all,
>
> Why do I get a warning from gcc with the following program?[/color]
[...][color=blue]
> printf("%i\n", f(n++) + n);[/color]
[...][color=blue]
> test.c:13: warning: operation on ‘n’ may be undefined[/color]

Because the the value of 'f(n++) + n' is undefined.
[color=blue]
> One of the sequence point cases is defined as: "The point of calling
> a function, after evaluating its arguments." If I got it right, that
> rule can be applied to `f(n++)' which is evaluated before `n' since
> addition is left associative. I can't see the ambiguity here.[/color]

The order of evaluation of the operands f(n++) and n is not defined.
Associativity (which isn't a C concept, anyway) doesn't enter into it.
Suman
Guest
 
Posts: n/a
#7: Nov 15 '05

re: Knowing your sequence points



Jack Klein wrote:[color=blue]
> On Thu, 11 Aug 2005 02:15:14 GMT, akarl <fusionfive@comhem.se> wrote
> in comp.lang.c:
>[color=green]
> > Hi all,
> >
> > Why do I get a warning from gcc with the following program?
> >
> > [test]$ cat test.c
> > #include <stdio.h>
> >
> > int f(int n)
> > {
> > return n;
> > }
> >
> >
> > int main(void)
> > {
> > int n = 0;
> >
> > printf("%i\n", f(n++) + n);
> > return 0;
> > }
> >
> > [test]$ gcc -Wall test.c
> > test.c: In function 'main':
> > test.c:13: warning: operation on 'n' may be undefined[/color]
>
> Yes, the operation on 'n' may be undefined. The standard says:
>
> "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."
>
> The printf() call in your call does not modify the value of 'n' more
> than once. The expression 'n++' modifies 'n' exactly once, and uses
> the original value of 'n' only for the purpose of computing the new
> value. But the '+ n' subexpression attempts to access the prior value
> of 'n' in a way that is not used in the computation of the new value.
>[color=green]
> > One of the sequence point cases is defined as: "The point of calling a
> > function, after evaluating its arguments." If I got it right, that rule
> > can be applied to `f(n++)' which is evaluated before `n' since addition
> > is left associative. I can't see the ambiguity here.[/color]
>
> No, you are wrong, associatively has nothing at all to do with order
> of evaluation. Only sequence points impose an order of evaluation.
>[color=green]
> > August
> >
> > (I would never write this kind of code in practice, but it's good to
> > know how the standard is defined.)[/color]
>
> Let's take an example that doesn't have undefined behavior:
>
> #include <stdio.h>
>
> int f1(void)
> {
> puts("function 1\n");
> return 1;
> }
>
> int f2(void)
> {
> puts("function 1\n");
> return 2;
> }
>
> int main(void)
> {
> printf("the sum is %d\n", f1() + f2());
> return 0;
> }
>
> This function does not define or contain any objects at all, so the
> paragraph I quoted from the standard certainly does not apply.
>
> Because the order of evaluation between sequence points is
> unspecified, the output could be either of the following two
> sequences, and must be one of the two:
>
> function 1
> function 2
> the sum is 3
>
> ...or:
>
> function 2
> function 1
> the sum is 3[/color]

<nitpick>
or more likely:
function 1
function 1
the sum is 3
</nitpick>
[color=blue]
> In fact, it may change between one and the other if you change the
> settings you use to invoke your compiler, for example enable or
> disable optimization.
>
> If just so happens that if your compiler evaluates the subexpression
> 'f(n++)' first, the result is defined because there is a sequence
> point imposed by calling the function before the '+ n' subexpression
> reads the value of 'n' again.
>
> But if your compiler evaluates 'n' in the '+ n' subexpression before
> evaluating the 'f(n++)' subexpression, there is no sequence point
> between the unrelated read and the modification, the behavior is
> undefined.
>
> Finally, since the order of evaluation is something the standard
> states is unspecified, it means that the compiler does not have to
> tell you which order it uses, and is free to change it based on
> settings, the day of the week, or the phase of the moon.
>
> Since one of the unspecified paths generates undefined behavior, the
> whole thing should be treated as undefined.
>
> --
> Jack Klein
> Home: http://JK-Technology.Com
> FAQs for
> comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
> comp.lang.c++ http://www.parashift.com/c++-faq-lite/
> alt.comp.lang.learn.c-c++
> http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html[/color]

Jack Klein
Guest
 
Posts: n/a
#8: Nov 15 '05

re: Knowing your sequence points


On 10 Aug 2005 23:55:56 -0700, "Suman" <skarpio@gmail.com> wrote in
comp.lang.c:
[color=blue]
> Jack Klein wrote:[/color]

[snip]
[color=blue][color=green]
> > Let's take an example that doesn't have undefined behavior:
> >
> > #include <stdio.h>
> >
> > int f1(void)
> > {
> > puts("function 1\n");
> > return 1;
> > }
> >
> > int f2(void)
> > {
> > puts("function 1\n");
> > return 2;
> > }
> >
> > int main(void)
> > {
> > printf("the sum is %d\n", f1() + f2());
> > return 0;
> > }
> >
> > This function does not define or contain any objects at all, so the
> > paragraph I quoted from the standard certainly does not apply.
> >
> > Because the order of evaluation between sequence points is
> > unspecified, the output could be either of the following two
> > sequences, and must be one of the two:
> >
> > function 1
> > function 2
> > the sum is 3
> >
> > ...or:
> >
> > function 2
> > function 1
> > the sum is 3[/color]
>
> <nitpick>
> or more likely:
> function 1
> function 1
> the sum is 3
> </nitpick>[/color]

Kind of takes the away the whole point of the example, doesn't it?
Makes it really, really indeterminate!

Thanks, Suman, nice catch.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://www.eskimo.com/~scs/C-faq/top.html
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~a...FAQ-acllc.html
Closed Thread