Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #20303 > unrolled thread

List of undefined behaviour and other sneeky bugs

Started byJohn Reye <jononanon@googlemail.com>
First post2012-05-03 10:04 -0700
Last post2012-05-08 06:19 -0700
Articles 17 on this page of 57 — 12 participants

Back to article view | Back to comp.lang.c


Contents

  List of undefined behaviour and other sneeky bugs John Reye <jononanon@googlemail.com> - 2012-05-03 10:04 -0700
    Re: List of undefined behaviour and other sneeky bugs jt@toerring.de (Jens Thoms Toerring) - 2012-05-03 17:38 +0000
      Re: List of undefined behaviour and other sneeky bugs John Reye <jononanon@googlemail.com> - 2012-05-03 10:50 -0700
        Re: List of undefined behaviour and other sneeky bugs Ben Pfaff <blp@cs.stanford.edu> - 2012-05-03 11:09 -0700
          Re: List of undefined behaviour and other sneeky bugs John Reye <jononanon@googlemail.com> - 2012-05-03 11:18 -0700
            Re: List of undefined behaviour and other sneeky bugs Ben Pfaff <blp@cs.stanford.edu> - 2012-05-03 11:24 -0700
              Re: List of undefined behaviour and other sneeky bugs John Reye <jononanon@googlemail.com> - 2012-05-03 11:35 -0700
                Re: List of undefined behaviour and other sneeky bugs John Reye <jononanon@googlemail.com> - 2012-05-03 11:56 -0700
                Re: List of undefined behaviour and other sneeky bugs Ben Pfaff <blp@cs.stanford.edu> - 2012-05-03 12:16 -0700
                  Re: List of undefined behaviour and other sneeky bugs John Reye <jononanon@googlemail.com> - 2012-05-03 12:20 -0700
                    Re: List of undefined behaviour and other sneeky bugs Keith Thompson <kst-u@mib.org> - 2012-05-03 12:39 -0700
            Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-07 17:51 -0700
              Re: List of undefined behaviour and other sneeky bugs "Joachim Schmitz" <nospam.jojo@schmitz-digital.de> - 2012-05-08 09:10 +0200
                Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-08 05:31 -0700
        Re: List of undefined behaviour and other sneeky bugs jt@toerring.de (Jens Thoms Toerring) - 2012-05-03 18:11 +0000
          Re: List of undefined behaviour and other sneeky bugs John Reye <jononanon@googlemail.com> - 2012-05-03 11:29 -0700
            Re: List of undefined behaviour and other sneeky bugs jt@toerring.de (Jens Thoms Toerring) - 2012-05-03 19:19 +0000
              Re: List of undefined behaviour and other sneeky bugs John Reye <jononanon@googlemail.com> - 2012-05-03 13:31 -0700
                Re: List of undefined behaviour and other sneeky bugs John Reye <jononanon@googlemail.com> - 2012-05-03 14:18 -0700
                  Re: List of undefined behaviour and other sneeky bugs John Reye <jononanon@googlemail.com> - 2012-05-03 15:20 -0700
              Re: List of undefined behaviour and other sneeky bugs Nobody <nobody@nowhere.com> - 2012-05-04 01:47 +0100
        Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-07 17:47 -0700
      Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-07 17:45 -0700
        Re: List of undefined behaviour and other sneeky bugs nick_keighley_nospam@hotmail.com - 2012-05-08 00:43 -0700
          Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-08 06:17 -0700
    Re: List of undefined behaviour and other sneeky bugs Keith Thompson <kst-u@mib.org> - 2012-05-03 12:46 -0700
      Re: List of undefined behaviour and other sneeky bugs John Reye <jononanon@googlemail.com> - 2012-05-03 13:35 -0700
        Re: List of undefined behaviour and other sneeky bugs Ben Pfaff <blp@cs.stanford.edu> - 2012-05-03 14:05 -0700
          Re: List of undefined behaviour and other sneeky bugs John Reye <jononanon@googlemail.com> - 2012-05-03 14:11 -0700
            Re: List of undefined behaviour and other sneeky bugs Ben Pfaff <blp@cs.stanford.edu> - 2012-05-03 15:02 -0700
              Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-07 18:10 -0700
                Re: List of undefined behaviour and other sneeky bugs nick_keighley_nospam@hotmail.com - 2012-05-08 00:49 -0700
                  Re: List of undefined behaviour and other sneeky bugs James Kuyper <jameskuyper@verizon.net> - 2012-05-08 06:37 -0400
                    Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-08 07:49 -0700
                  Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-08 07:25 -0700
                Re: List of undefined behaviour and other sneeky bugs Ben Pfaff <blp@cs.stanford.edu> - 2012-05-08 09:46 -0700
            Re: List of undefined behaviour and other sneeky bugs James Kuyper <jameskuyper@verizon.net> - 2012-05-03 18:24 -0400
              Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-07 18:24 -0700
        Re: List of undefined behaviour and other sneeky bugs jt@toerring.de (Jens Thoms Toerring) - 2012-05-03 21:17 +0000
          Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-07 18:28 -0700
        Re: List of undefined behaviour and other sneeky bugs Keith Thompson <kst-u@mib.org> - 2012-05-03 15:54 -0700
        Re: List of undefined behaviour and other sneeky bugs Old Wolf <oldwolf@inspire.net.nz> - 2012-05-06 22:32 -0700
          Re: List of undefined behaviour and other sneeky bugs Jens Gustedt <jens.gustedt@loria.fr> - 2012-05-07 08:26 +0200
          Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-07 18:31 -0700
      Re: List of undefined behaviour and other sneeky bugs Jens Gustedt <jens.gustedt@loria.fr> - 2012-05-03 23:18 +0200
        Re: List of undefined behaviour and other sneeky bugs Keith Thompson <kst-u@mib.org> - 2012-05-03 15:58 -0700
    Re: List of undefined behaviour and other sneeky bugs pete <pfiland@mindspring.com> - 2012-05-04 00:25 -0400
      Re: List of undefined behaviour and other sneeky bugs John Reye <jononanon@googlemail.com> - 2012-05-03 22:28 -0700
        Re: List of undefined behaviour and other sneeky bugs James Kuyper <jameskuyper@verizon.net> - 2012-05-04 07:33 -0400
          Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-07 19:20 -0700
        Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-07 18:50 -0700
      Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-07 18:42 -0700
        Re: List of undefined behaviour and other sneeky bugs pete <pfiland@mindspring.com> - 2012-05-07 23:45 -0400
          Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-07 23:01 -0700
            Re: List of undefined behaviour and other sneeky bugs pete <pfiland@mindspring.com> - 2012-05-08 06:28 -0400
              Re: List of undefined behaviour and other sneeky bugs pete <pfiland@mindspring.com> - 2012-05-08 06:37 -0400
                Re: List of undefined behaviour and other sneeky bugs Tim Rentsch <txr@alumni.caltech.edu> - 2012-05-08 06:19 -0700

Page 3 of 3 — ← Prev page 1 2 [3]


#20363

FromKeith Thompson <kst-u@mib.org>
Date2012-05-03 15:54 -0700
Message-ID<lnfwbgooxy.fsf@nuthaus.mib.org>
In reply to#20344
John Reye <jononanon@googlemail.com> writes:
> On May 3, 9:46 pm, Keith Thompson <ks...@mib.org> wrote:
>> As for whether it "works", that depends on what you want it to do.  It
>> stores the value 0x12 in mystruct.u.c, which is also the first byte of
>> mystruct.u.b.  If you access the first byte of mystruct.u.b,
>> *(char*)&mystruct.u.b, you'll get 0x12.  If you access mystruct.u.b as
>> an int, you'll get garbage, possibly a trap representation.
> Will I really get garbage? I think not. The lowest-addressed byte is
> 0x12, and the other bytes of mystruct.u.b are what they were before,
> right?
> A trap? How can that possibly be justified? Why does the C language
> have unions then? What is the intended use of unions?

No, the other bytes are not *necessarily* what they were before.

N1570 6.2.6.1p7 (I think it's already been quoted in this thread):

    When a value is stored in a member of an object of union type,
    the bytes of the object representation that do not correspond to
    that member but do correspond to other members take unspecified
    values.

If that other member's type has trap representations, then the
unspecified byte values could cause that member to take on a trap
representation.

If you really want to store 0x12 in the lowest-addressed byte of an int
without touching the other bytes, you can do it like this:

    *(char*)&int_obj = 0x12;

But that's a somewhat odd thing to do.  What goal are you trying to
achieve by storing 0x12 in the lowest-addressed byte of an int?  If
you'll tell us that, perhaps we can help you find a better solution.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
    Will write code for food.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#20439

FromOld Wolf <oldwolf@inspire.net.nz>
Date2012-05-06 22:32 -0700
Message-ID<ad3bf86e-136a-4c46-a6c5-77c0e8c5bbb2@ns1g2000pbc.googlegroups.com>
In reply to#20344
On May 4, 8:35 am, John Reye <jonona...@googlemail.com> wrote:
> A trap? How can that possibly be justified? Why does the C language
> have unions then? What is the intended use of unions?

Unions are for saving memory, when you know you
need to store a value of some sort, but the value
could be one of various types. If there were no
unions you'd either have to have a struct (wasting
memory), or use a byte buffer and write some ugly
cast and alignment stuff.

They're not supposed to be a hack to do type conversions,
although that hasn't stopped people trying that over the years :)

[toc] | [prev] | [next] | [standalone]


#20441

FromJens Gustedt <jens.gustedt@loria.fr>
Date2012-05-07 08:26 +0200
Message-ID<4FA76B25.6030908@loria.fr>
In reply to#20439
On 05/07/2012 07:32 AM, Old Wolf wrote:
> On May 4, 8:35 am, John Reye <jonona...@googlemail.com> wrote:
>> A trap? How can that possibly be justified? Why does the C language
>> have unions then? What is the intended use of unions?
> 
> Unions are for saving memory, when you know you
> need to store a value of some sort, but the value
> could be one of various types. If there were no
> unions you'd either have to have a struct (wasting
> memory), or use a byte buffer and write some ugly
> cast and alignment stuff.
> 
> They're not supposed to be a hack to do type conversions,
> although that hasn't stopped people trying that over the years :)

This is not hacking this is foreseen as such by the standard:

 -  Unions have been the only way to guarantee that an object is
correctly aligned for a collection of types. (Since C11 there are also
_Alignas and friends.)
 -  Other than casting pointers, unions avoid aliasing problems.

Jens

[toc] | [prev] | [next] | [standalone]


#20483

FromTim Rentsch <txr@alumni.caltech.edu>
Date2012-05-07 18:31 -0700
Message-ID<kfnipg7xxuo.fsf@x-alumni2.alumni.caltech.edu>
In reply to#20439
Old Wolf <oldwolf@inspire.net.nz> writes:

> On May 4, 8:35 am, John Reye <jonona...@googlemail.com> wrote:
>> A trap? How can that possibly be justified? Why does the C language
>> have unions then? What is the intended use of unions?
>
> Unions are for saving memory, when you know you
> need to store a value of some sort, but the value
> could be one of various types. If there were no
> unions you'd either have to have a struct (wasting
> memory), or use a byte buffer and write some ugly
> cast and alignment stuff.
>
> They're not supposed to be a hack to do type conversions,
> [snip]

In fact they were, and are.  And that's why the Standard
defines how such cases work.

[toc] | [prev] | [next] | [standalone]


#20355

FromJens Gustedt <jens.gustedt@loria.fr>
Date2012-05-03 23:18 +0200
Message-ID<4FA2F620.5080305@loria.fr>
In reply to#20338
Am 05/03/2012 09:46 PM, schrieb Keith Thompson:
> John Reye <jononanon@googlemail.com> writes:
> [...]
>>                   struct
>>                   {
>>                      char a;
>>                      union {
>>                         int  b;
>>                         char c;
>>                      };
>>                   } mystruct;
>>                   mystruct.c = 0x12
>>
>> Would this union work on every platform??
> 
> You have an unnamed union.  Some compilers support this as an extension,
> but it's not valid in standard C.

C11 has anonymous structures and unions (6.7.2.1 p 13)

Jens

[toc] | [prev] | [next] | [standalone]


#20364

FromKeith Thompson <kst-u@mib.org>
Date2012-05-03 15:58 -0700
Message-ID<lnbom4oosd.fsf@nuthaus.mib.org>
In reply to#20355
Jens Gustedt <jens.gustedt@loria.fr> writes:
> Am 05/03/2012 09:46 PM, schrieb Keith Thompson:
>> John Reye <jononanon@googlemail.com> writes:
>> [...]
>>>                   struct
>>>                   {
>>>                      char a;
>>>                      union {
>>>                         int  b;
>>>                         char c;
>>>                      };
>>>                   } mystruct;
>>>                   mystruct.c = 0x12
>>>
>>> Would this union work on every platform??
>> 
>> You have an unnamed union.  Some compilers support this as an extension,
>> but it's not valid in standard C.
>
> C11 has anonymous structures and unions (6.7.2.1 p 13)

Interesting.

Here's the paragraph (quoting N1570):

    An unnamed member whose type specifier is a structure specifier
    with no tag is called an *anonymous structure*; an unnamed member
    whose type specifier is a union specifier with no tag is called
    an *anonymous union*. The members of an anonymous structure or
    union are considered to be members of the containing structure
    or union. This applies recursively if the containing structure
    or union is also anonymous.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
    Will write code for food.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#20371

Frompete <pfiland@mindspring.com>
Date2012-05-04 00:25 -0400
Message-ID<4FA35A2E.6B0B@mindspring.com>
In reply to#20303
John Reye wrote:
> 
> 1)
>                   a[i] = i++;
> 
> http://c-faq.com/expr/evalorder1.html
> 
> So this attempt at optimisation is wrong:
> 
>                   int i;
>                   int a[10];
>                   for (i = 0; i < sizeof(a); )
>                      a[i] = i++;       /* set a to {1, 2, 3, ...} */
> 
> Correctly optimized, it should be:
>                   for (i = 0; i < sizeof(a); )
>                      i = a[i] = i+1;   /* set a to {1, 2, 3, ...} */

No. That's wrong.
Concerning
    i = a[i] = i+1;
Assignment, is not a sequence point.
The above code does not say whether the value of (i+1)
is stored first in (a[i]) or in (i).


This is defined:

    for (i = 0; i < sizeof a / sizeof *a; ++i) {
        a[i] = i + 1;       		/* set a to {1, 2, 3, ...} */
    }

-- 
pete

[toc] | [prev] | [next] | [standalone]


#20372

FromJohn Reye <jononanon@googlemail.com>
Date2012-05-03 22:28 -0700
Message-ID<6d809568-c4a1-4223-ada2-5e031db0e896@l15g2000vbv.googlegroups.com>
In reply to#20371
On May 4, 6:25 am, pete <pfil...@mindspring.com> wrote:
> No. That's wrong.
> Concerning
>     i = a[i] = i+1;
> Assignment, is not a sequence point.
> The above code does not say whether the value of (i+1)
> is stored first in (a[i]) or in (i).
>
> This is defined:
>
>     for (i = 0; i < sizeof a / sizeof *a; ++i) {
>         a[i] = i + 1;                   /* set a to {1, 2, 3, ...} */
>     }
>
> --
> pete

I believe that is incorrect.
The sequence point only makes a difference for statements that contain
side-effects.
So this is not allowed
   a[i] = i++;
because = is no sequence point, and contains side-effects (i++).
See http://c-faq.com/expr/seqpoints.html




But this is very much allowed:
i = a[i] = i+1;
It uses the normal fact assignment is right-associative and that no
side-effects exist.



Also (less importantly): it may be more efficient than doing
a[i] = i+1;
i++;

since I am helping an exessively "simple" compiler understand, that it
need not load i into a register for the 2nd line (to then be
incremented). Instead, the incremented value (i+1) may already be in a
register, and (after the loop... if i is still needed) ready to be
written to the memory-location of i.

[toc] | [prev] | [next] | [standalone]


#20383

FromJames Kuyper <jameskuyper@verizon.net>
Date2012-05-04 07:33 -0400
Message-ID<jo0eqg$97q$1@dont-email.me>
In reply to#20372
On 05/04/2012 01:28 AM, John Reye wrote:
> On May 4, 6:25�am, pete <pfil...@mindspring.com> wrote:
>> No. That's wrong.
>> Concerning
>> � � i = a[i] = i+1;
>> Assignment, is not a sequence point.
>> The above code does not say whether the value of (i+1)
>> is stored first in (a[i]) or in (i).
>>
>> This is defined:
>>
>> � � for (i = 0; i < sizeof a / sizeof *a; ++i) {
>> � � � � a[i] = i + 1; � � � � � � � � � /* set a to {1, 2, 3, ...} */
>> � � }
>>
>> --
>> pete
> 
> I believe that is incorrect.
> The sequence point only makes a difference for statements that contain
> side-effects.
> So this is not allowed
>    a[i] = i++;
> because = is no sequence point, and contains side-effects (i++).
> See http://c-faq.com/expr/seqpoints.html
> 
> 
> 
> 
> But this is very much allowed:
> i = a[i] = i+1;
> It uses the normal fact assignment is right-associative and that no
> side-effects exist.

That statement reflects a common misunderstanding of what "side-effect"
means. You might think that the fact that i=3 sets the value of i to 3
is the main effect; the fact that i=3 is itself an expression with a
value of 3 is less important (it's certainly not a fact that I use very
often). However, what the standard sees things the other way around. It
says:

> Accessing a volatile object, modifying an object, modifying a file, or calling a function
> that does any of those operations are all _side effects_, (5.1.2.3p2)

I've used underscores to mark the fact that "side effect" is in italics,
which is the standard's convention for marking this sentence as the
definition of the italicized term. The expression "i = a[i] = i + 1"
modifies two objects: 'i' and a[i], so it does indeed have side effects.

In C99, the expression "i = a[i] = i + 1" had undefined behavior because
the value of i was both stored by this expression, and read for purposes
other than determining the value to be stored in 'i', without any
intervening sequence points to determine which of those events occurs
first. The exception for determining the value to be stored allows "i =
i + 1", since the value of 'i' must be read in order to calculate the
value of 'i+1' which is to be stored in i.

However, in the case of 'i = a[i] = i+1", the value of 'i' is also read
to determine which element of 'a' gets updated. It's unclear whether the
value of i should be updated before or after determining which element
to update. The C committee could have chosen to specify the sequence,
but they reached the conclusion that such code is inherently confusing,
and therefore should be discouraged. They did this by not merely leaving
the sequence unspecified, but explicitly stating that the behavior of
your entire program is undefined if it uses such code. The standard
never says that you can't do something; it only tells you what you can
and cannot depend upon happening, if you should choose to do something.
In this case, the standard imposes NO requirements on the behavior of a
program containing such code; you can't even count on it being allowed
to compile.

This is not a hard requirement to work around. Just make the desired
sequence crystal clear by writing either:

	a[i] = i + 1;
	i = a[i];

or

	i = i + 1;
	a[i] = i;

whichever one matches what you actually intended i=a[i]= i+1 to do.

The relevant clause in C99 was one of the most confusingly worded parts
of that standard, and provoked a lot of argument. In C2011, I gather
that this whole issue has been more precisely defined by rewording
things in terms of the "visible sequence of side effect" and by
specifying that the evaluation of each expression may be "sequenced
before", "sequenced after", or "indeterminately sequenced" relative to
the evaluation of other expressions. The C2011 wording is greatly
complicated by the fact that it must now deal with the possibility of
multi-threaded code. As a result, I've not had time to review exactly
what the new standard says about such things. The new wording might make
the behavior of this code well-defined; but I doubt it - I think the
committee still believes that such code is inherently confusing, and
therefore should still be discouraged.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#20487

FromTim Rentsch <txr@alumni.caltech.edu>
Date2012-05-07 19:20 -0700
Message-ID<kfn62c7xvjt.fsf@x-alumni2.alumni.caltech.edu>
In reply to#20383
James Kuyper <jameskuyper@verizon.net> writes:

> On 05/04/2012 01:28 AM, John Reye wrote:
>> On May 4, 6:25 am, pete <pfil...@mindspring.com> wrote:
>>> No. That's wrong.
>>> Concerning
>>>     i = a[i] = i+1;
>>> Assignment, is not a sequence point.
>>> The above code does not say whether the value of (i+1)
>>> is stored first in (a[i]) or in (i).
>>>
>>> This is defined:
>>>
>>>     for (i = 0; i < sizeof a / sizeof *a; ++i) {
>>>         a[i] = i + 1;                   /* set a to {1, 2, 3, ...} */
>>>     }
>>>
>>> --
>>> pete
>> 
>> I believe that is incorrect.
>> The sequence point only makes a difference for statements that contain
>> side-effects.
>> So this is not allowed
>>    a[i] = i++;
>> because = is no sequence point, and contains side-effects (i++).
>> See http://c-faq.com/expr/seqpoints.html
>> 
>> 
>> 
>> 
>> But this is very much allowed:
>> i = a[i] = i+1;
>> It uses the normal fact assignment is right-associative and that no
>> side-effects exist.
>
> [snip description of side-effects]
>
> In C99, the expression "i = a[i] = i + 1" had undefined behavior because
> the value of i was both stored by this expression, and read for purposes
> other than determining the value to be stored in 'i', without any
> intervening sequence points to determine which of those events occurs
> first. The exception for determining the value to be stored allows "i =
> i + 1", since the value of 'i' must be read in order to calculate the
> value of 'i+1' which is to be stored in i.
>
> However, in the case of 'i = a[i] = i+1", the value of 'i' is also read
> to determine which element of 'a' gets updated. It's unclear whether the
> value of i should be updated before or after determining which element
> to update. The C committee could have chosen to specify the sequence,
> but they reached the conclusion that such code is inherently confusing,
> and therefore should be discouraged. [snip elaboration]

There is evidence to the contrary, namely that they intended all
along that such uses be well-defined, and it was only due to a
poor choice of wording (in earlier Standards) that it wasn't.
It is unambiguously well-defined under C11.


> The relevant clause in C99 was one of the most confusingly
> worded parts of that standard, and provoked a lot of argument.

I would say it was poorly worded rather than confusingly
worded;  IMO the meaning was clear, it was just a poor
choice of phrasing that caused confusion.  In any case,
C11 has fixed that.

> In C2011, I gather
> that this whole issue has been more precisely defined by rewording
> things in terms of the "visible sequence of side effect" and by
> specifying that the evaluation of each expression may be "sequenced
> before", "sequenced after", or "indeterminately sequenced" relative to
> the evaluation of other expressions. The C2011 wording is greatly
> complicated by the fact that it must now deal with the possibility of
> multi-threaded code. As a result, I've not had time to review exactly
> what the new standard says about such things. The new wording might make
> the behavior of this code well-defined; but I doubt it - I think the
> committee still believes that such code is inherently confusing, and
> therefore should still be discouraged.

So although he hasn't read what it says exactly, he feels
free to conjecture what it does say?  That's amusing.

Having taken some amount of time to study the documents available
on how to specify order of evaluation, including C11, I would
say this --

First, the behavior in question is well-defined under C11.

Second, several formal models for how "order of evaluation"
should be specified in C were discussed over the years by the
committee, and AFAIK all of them defined the semantics of
multiple assignments like this one;  certainly the ones I
remember reading did, and the current one (in C11) does.  So all
the evidence I've seen supports the idea that the committee
thought it important to define such cases, and I'm not aware of
any evidence that supports the view that the committee believes
such code is confusing or should be discouraged.

But in any case, under C11 the behavior is well-defined.

[toc] | [prev] | [next] | [standalone]


#20485

FromTim Rentsch <txr@alumni.caltech.edu>
Date2012-05-07 18:50 -0700
Message-ID<kfnaa1jxwyc.fsf@x-alumni2.alumni.caltech.edu>
In reply to#20372
John Reye <jononanon@googlemail.com> writes:

> On May 4, 6:25 am, pete <pfil...@mindspring.com> wrote:
>> No. That's wrong.
>> Concerning
>>     i = a[i] = i+1;
>> Assignment, is not a sequence point.
>> The above code does not say whether the value of (i+1)
>> is stored first in (a[i]) or in (i).
>>
>> This is defined:
>>
>>     for (i = 0; i < sizeof a / sizeof *a; ++i) {
>>         a[i] = i + 1;                   /* set a to {1, 2, 3, ...} */
>>     }
>>
>> --
>> pete
>
> I believe that is incorrect.
> The sequence point only makes a difference for statements that contain
> side-effects.
> So this is not allowed
>    a[i] = i++;
> because = is no sequence point, and contains side-effects (i++).
> See http://c-faq.com/expr/seqpoints.html

The latest C standard uses more precise terminology regarding
sequencing.  If you haven't gotten that, or this close approximation

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

, I encourage you to do so.


> But this is very much allowed:
> i = a[i] = i+1;
> It uses the normal fact assignment is right-associative and that no
> side-effects exist.  [snip]

You're right that it is allowed.  However there are two side-effects
(ie, the assignments), and being right-associative plays into
the question only partially.  What is more important is that
the side-effect of storing into 'i' is /sequenced after/ the
value computations of the two operands (which in this case
are 'i' and 'a[i] = i+1').  It is because of that sequencing
relationship that the store into 'i' must follow the computation
of which element a is to be accessed with the expression 'a[i]'.

[toc] | [prev] | [next] | [standalone]


#20484

FromTim Rentsch <txr@alumni.caltech.edu>
Date2012-05-07 18:42 -0700
Message-ID<kfnehqvxxcg.fsf@x-alumni2.alumni.caltech.edu>
In reply to#20371
pete <pfiland@mindspring.com> writes:

> John Reye wrote:
>> 
>> 1)
>>                   a[i] = i++;
>> 
>> http://c-faq.com/expr/evalorder1.html
>> 
>> So this attempt at optimisation is wrong:
>> 
>>                   int i;
>>                   int a[10];
>>                   for (i = 0; i < sizeof(a); )
>>                      a[i] = i++;       /* set a to {1, 2, 3, ...} */
>> 
>> Correctly optimized, it should be:
>>                   for (i = 0; i < sizeof(a); )
>>                      i = a[i] = i+1;   /* set a to {1, 2, 3, ...} */
>
> No. That's wrong.
> Concerning
>     i = a[i] = i+1;
> Assignment, is not a sequence point.
> The above code does not say whether the value of (i+1)
> is stored first in (a[i]) or in (i).  [snip alternative]

The behavior of

    i = a[i] = i+1;

is well-defined.  I refer you to 6.5.16 p3 in N1570, specifically
the second-to-last sentence.  By the time the store into 'i'
commences, the value (lvalue) computation of 'a[i]' has already
completed, because it is sequenced before delivering the value
to be stored into 'i'.

The stores to 'i' and 'a[i]' may happen in any order, but the
lvalue 'a[i]' must be determined before any store into 'i'.

[toc] | [prev] | [next] | [standalone]


#20488

Frompete <pfiland@mindspring.com>
Date2012-05-07 23:45 -0400
Message-ID<4FA896E6.B8E@mindspring.com>
In reply to#20484
Tim Rentsch wrote:
> 
> pete <pfiland@mindspring.com> writes:
> 
> > John Reye wrote:
> >>
> >> 1)
> >>                   a[i] = i++;
> >>
> >> http://c-faq.com/expr/evalorder1.html
> >>
> >> So this attempt at optimisation is wrong:
> >>
> >>                   int i;
> >>                   int a[10];
> >>                   for (i = 0; i < sizeof(a); )
> >>                      a[i] = i++;       /* set a to {1, 2, 3, ...} */
> >>
> >> Correctly optimized, it should be:
> >>                   for (i = 0; i < sizeof(a); )
> >>                      i = a[i] = i+1;   /* set a to {1, 2, 3, ...} */
> >
> > No. That's wrong.
> > Concerning
> >     i = a[i] = i+1;
> > Assignment, is not a sequence point.
> > The above code does not say whether the value of (i+1)
> > is stored first in (a[i]) or in (i).  [snip alternative]
> 
> The behavior of
> 
>     i = a[i] = i+1;
> 
> is well-defined.  I refer you to 6.5.16 p3 in N1570, specifically
> the second-to-last sentence.  By the time the store into 'i'
> commences, the value (lvalue) computation of 'a[i]' has already
> completed, because it is sequenced before delivering the value
> to be stored into 'i'.
> 
> The stores to 'i' and 'a[i]' may happen in any order, but the
> lvalue 'a[i]' must be determined before any store into 'i'.

I don't see where it says what you say that it says.

Concerning (a[i] = i+1),
"the value of the left operand after the assignment"
can be determined before the assignment
and without knowing which array element a[i] refers to.

You don't have to know which array element a[i] refers to,
to know 
what the value of (i+1) converted to whichever type (a[i]) has, 
is.

n1570
6.5.16 Assignment operators
Semantics
3 An assignment operator stores a value 
  in the object designated by the left operand. 
  An assignment expression has 
  the value of the left operand after the assignment,111) 
  but is not an lvalue. 
  The type of an assignment expression 
  is the type the left operand would have after lvalue conversion. 
  The side effect of updating the stored value of the left operand 
  is sequenced after the value computations of the left 
  and right operands. 
  The evaluations of the operands are unsequenced.

-- 
pete

[toc] | [prev] | [next] | [standalone]


#20490

FromTim Rentsch <txr@alumni.caltech.edu>
Date2012-05-07 23:01 -0700
Message-ID<kfnsjfbw6rt.fsf@x-alumni2.alumni.caltech.edu>
In reply to#20488
pete <pfiland@mindspring.com> writes:

> Tim Rentsch wrote:
>> 
>> pete <pfiland@mindspring.com> writes:
>> 
>> > John Reye wrote:
>> >>
>> >> 1)
>> >>                   a[i] = i++;
>> >>
>> >> http://c-faq.com/expr/evalorder1.html
>> >>
>> >> So this attempt at optimisation is wrong:
>> >>
>> >>                   int i;
>> >>                   int a[10];
>> >>                   for (i = 0; i < sizeof(a); )
>> >>                      a[i] = i++;       /* set a to {1, 2, 3, ...} */
>> >>
>> >> Correctly optimized, it should be:
>> >>                   for (i = 0; i < sizeof(a); )
>> >>                      i = a[i] = i+1;   /* set a to {1, 2, 3, ...} */
>> >
>> > No. That's wrong.
>> > Concerning
>> >     i = a[i] = i+1;
>> > Assignment, is not a sequence point.
>> > The above code does not say whether the value of (i+1)
>> > is stored first in (a[i]) or in (i).  [snip alternative]
>> 
>> The behavior of
>> 
>>     i = a[i] = i+1;
>> 
>> is well-defined.  I refer you to 6.5.16 p3 in N1570, specifically
>> the second-to-last sentence.  By the time the store into 'i'
>> commences, the value (lvalue) computation of 'a[i]' has already
>> completed, because it is sequenced before delivering the value
>> to be stored into 'i'.
>> 
>> The stores to 'i' and 'a[i]' may happen in any order, but the
>> lvalue 'a[i]' must be determined before any store into 'i'.
>
> I don't see where it says what you say that it says.
>
> Concerning (a[i] = i+1),
> "the value of the left operand after the assignment"
> can be determined before the assignment
> and without knowing which array element a[i] refers to.
>
> You don't have to know which array element a[i] refers to,
> to know 
> what the value of (i+1) converted to whichever type (a[i]) has, 
> is.
>
> n1570
> 6.5.16 Assignment operators
> Semantics
> 3 An assignment operator stores a value 
>   in the object designated by the left operand. 
>   An assignment expression has 
>   the value of the left operand after the assignment,111) 
>   but is not an lvalue. 
>   The type of an assignment expression 
>   is the type the left operand would have after lvalue conversion. 
>   The side effect of updating the stored value of the left operand 
>   is sequenced after the value computations of the left 
>   and right operands. 
>   The evaluations of the operands are unsequenced.

The missing piece (which I should have mentioned before -
sorry about that) is 6.5 p1, last sentence:

   The value computations of the operands of an operator are
   sequenced before the value computation of the result of
   the operator.

So the lvalue 'a[i]' must be computed before there is a value
(produced by the intermediate '=' operator) to store into 'i'.

[toc] | [prev] | [next] | [standalone]


#20496

Frompete <pfiland@mindspring.com>
Date2012-05-08 06:28 -0400
Message-ID<4FA8F568.4D99@mindspring.com>
In reply to#20490
Tim Rentsch wrote:
> 
> pete <pfiland@mindspring.com> writes:
> 
> > Tim Rentsch wrote:
> >>
> >> pete <pfiland@mindspring.com> writes:
> >>
> >> > John Reye wrote:
> >> >>
> >> >> 1)
> >> >>                   a[i] = i++;
> >> >>
> >> >> http://c-faq.com/expr/evalorder1.html
> >> >>
> >> >> So this attempt at optimisation is wrong:
> >> >>
> >> >>                   int i;
> >> >>                   int a[10];
> >> >>                   for (i = 0; i < sizeof(a); )
> >> >>                      a[i] = i++;       /* set a to {1, 2, 3, ...} */
> >> >>
> >> >> Correctly optimized, it should be:
> >> >>                   for (i = 0; i < sizeof(a); )
> >> >>                      i = a[i] = i+1;   /* set a to {1, 2, 3, ...} */
> >> >
> >> > No. That's wrong.
> >> > Concerning
> >> >     i = a[i] = i+1;
> >> > Assignment, is not a sequence point.
> >> > The above code does not say whether the value of (i+1)
> >> > is stored first in (a[i]) or in (i).  [snip alternative]
> >>
> >> The behavior of
> >>
> >>     i = a[i] = i+1;
> >>
> >> is well-defined.  I refer you to 6.5.16 p3 in N1570, specifically
> >> the second-to-last sentence.  By the time the store into 'i'
> >> commences, the value (lvalue) computation of 'a[i]' has already
> >> completed, because it is sequenced before delivering the value
> >> to be stored into 'i'.
> >>
> >> The stores to 'i' and 'a[i]' may happen in any order, but the
> >> lvalue 'a[i]' must be determined before any store into 'i'.
> >
> > I don't see where it says what you say that it says.
> >
> > Concerning (a[i] = i+1),
> > "the value of the left operand after the assignment"
> > can be determined before the assignment
> > and without knowing which array element a[i] refers to.
> >
> > You don't have to know which array element a[i] refers to,
> > to know
> > what the value of (i+1) converted to whichever type (a[i]) has,
> > is.
> >
> > n1570
> > 6.5.16 Assignment operators
> > Semantics
> > 3 An assignment operator stores a value
> >   in the object designated by the left operand.
> >   An assignment expression has
> >   the value of the left operand after the assignment,111)
> >   but is not an lvalue.
> >   The type of an assignment expression
> >   is the type the left operand would have after lvalue conversion.
> >   The side effect of updating the stored value of the left operand
> >   is sequenced after the value computations of the left
> >   and right operands.
> >   The evaluations of the operands are unsequenced.
> 
> The missing piece (which I should have mentioned before -
> sorry about that) is 6.5 p1, last sentence:
> 
>    The value computations of the operands of an operator are
>    sequenced before the value computation of the result of
>    the operator.
> 
> So the lvalue 'a[i]' must be computed before there is a value
> (produced by the intermediate '=' operator) to store into 'i'.

I think that you may be right.
I also made an obsolete statement elsewhere in this thread
about the postfix increment operator.

-- 
pete

[toc] | [prev] | [next] | [standalone]


#20499

Frompete <pfiland@mindspring.com>
Date2012-05-08 06:37 -0400
Message-ID<4FA8F767.689F@mindspring.com>
In reply to#20496
pete wrote:
> 
> Tim Rentsch wrote:

> >    The value computations of the operands of an operator are
> >    sequenced before the value computation of the result of
> >    the operator.
> >
> > So the lvalue 'a[i]' must be computed before there is a value
> > (produced by the intermediate '=' operator) to store into 'i'.
> 
> I think that you may be right.
> I also made an obsolete statement elsewhere in this thread
> about the postfix increment operator.

 Actually, it was in the "pointer arithmetic question" thread.

-- 
pete

[toc] | [prev] | [next] | [standalone]


#20508

FromTim Rentsch <txr@alumni.caltech.edu>
Date2012-05-08 06:19 -0700
Message-ID<kfnfwbax12o.fsf@x-alumni2.alumni.caltech.edu>
In reply to#20499
pete <pfiland@mindspring.com> writes:

> pete wrote:
>> 
>> Tim Rentsch wrote:
>
>> >    The value computations of the operands of an operator are
>> >    sequenced before the value computation of the result of
>> >    the operator.
>> >
>> > So the lvalue 'a[i]' must be computed before there is a value
>> > (produced by the intermediate '=' operator) to store into 'i'.
>> 
>> I think that you may be right.
>> I also made an obsolete statement elsewhere in this thread
>> about the postfix increment operator.
>
>  Actually, it was in the "pointer arithmetic question" thread.

Aha, I see that...  will respond there.

[toc] | [prev] | [standalone]


Page 3 of 3 — ← Prev page 1 2 [3]

Back to top | Article view | comp.lang.c


csiph-web