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


Groups > comp.std.c > #1840 > unrolled thread

Unsequenced Side Effects on the Same Union

Started byShao Miller <sha0.miller@gmail.com>
First post2013-01-15 22:32 -0500
Last post2013-01-18 15:07 -0500
Articles 9 — 4 participants

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


Contents

  Unsequenced Side Effects on the Same Union Shao Miller <sha0.miller@gmail.com> - 2013-01-15 22:32 -0500
    Re: Unsequenced Side Effects on the Same Union Nick Bowler <nbowler@draconx.ca> - 2013-01-16 14:55 +0000
      Re: Unsequenced Side Effects on the Same Union Shao Miller <sha0.miller@gmail.com> - 2013-01-16 10:53 -0500
      Re: Unsequenced Side Effects on the Same Union James Kuyper <jameskuyper@verizon.net> - 2013-01-16 11:04 -0500
        Re: Unsequenced Side Effects on the Same Union Nick Bowler <nbowler@draconx.ca> - 2013-01-16 20:56 +0000
          Re: Unsequenced Side Effects on the Same Union Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-17 13:21 -0800
            Re: Unsequenced Side Effects on the Same Union Shao Miller <sha0.miller@gmail.com> - 2013-01-17 17:50 -0500
              Re: Unsequenced Side Effects on the Same Union Tim Rentsch <txr@alumni.caltech.edu> - 2013-01-18 11:25 -0800
                Re: Unsequenced Side Effects on the Same Union Shao Miller <sha0.miller@gmail.com> - 2013-01-18 15:07 -0500

#1840 — Unsequenced Side Effects on the Same Union

FromShao Miller <sha0.miller@gmail.com>
Date2013-01-15 22:32 -0500
SubjectUnsequenced Side Effects on the Same Union
Message-ID<kd570b$mvc$1@dont-email.me>
   #include <stdio.h>

   void func1(void * vp1, void * vp2) {
       int * ip;
       double * dp;

       /* Populate ip and dp? */
       if (!vp1 && !vp2) {
           func1(&ip, &dp);

           /*
            * 6.5p2: Unsequenced side effects
            * on the same... Scalar?
            */
           printf("%f\n", (*ip = 42) + (*dp = 3.14));
         }

       /* Self-called? */
       if (vp1 && vp2) {
           /* Aliasing shoved down here */
           static union {
               int i;
               double d;
             } u;
           *(int **) vp1 = &u.i;
           *(double **) vp2 = &u.d;
         }
     }

   int main(void) { func1(NULL, NULL); return 0; }

Sorry all, I'm puzzled...  This surely yields undefined behaviour, but 
why, in C11?  6.5p2 changed from that of C99.  Is it because one of the 
'+' operands could establish an effective type before the other? 
Hopefully they are not simultaneous.

-- 
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.

Cheerily,"  -- Richard Harter

[toc] | [next] | [standalone]


#1843

FromNick Bowler <nbowler@draconx.ca>
Date2013-01-16 14:55 +0000
Message-ID<kd6f0b$fh4$1@dont-email.me>
In reply to#1840
On Tue, 15 Jan 2013 22:32:27 -0500, Shao Miller wrote:
> #include <stdio.h>
> 
>    void func1(void * vp1, void * vp2) {
>        int * ip;
>        double * dp;
> 
>        /* Populate ip and dp? */
>        if (!vp1 && !vp2) {
>            func1(&ip, &dp);
> 
>            /*
>             * 6.5p2: Unsequenced side effects
>             * on the same... Scalar?
>             */
>            printf("%f\n", (*ip = 42) + (*dp = 3.14));
>          }
> 
>        /* Self-called? */
>        if (vp1 && vp2) {
>            /* Aliasing shoved down here */
>            static union {
>                int i;
>                double d;
>              } u;
>            *(int **) vp1 = &u.i;
>            *(double **) vp2 = &u.d;
>          }
>      }
> 
>    int main(void) { func1(NULL, NULL); return 0; }
> 
> Sorry all, I'm puzzled...  This surely yields undefined behaviour, but 
> why, in C11?  6.5p2 changed from that of C99.  Is it because one of the 
> '+' operands could establish an effective type before the other?

I have a feeling that when the authors wrote "scalar object" in n1570
6.5p2 they had something specific in mind, but the term does not appear
to be defined anywhere in the standard.  The term also is not in the
index.  Perhaps this was corrected in the final standard which I do not
have a copy of.

"Scalar object" is also used in 5.1.2.4p14, where context suggests that
it at least excludes bit-fields.  It appears again in 5.1.2.4p19 with
context suggesting that it includes objects with atomic types.  It is
also used a couple times in Annex K, with context suggesting that it
does not include objects that are elements of arrays.

At the very least, the undefined term "scalar object" appears to
have absolutely nothing to do with the confusingly similarly-named
(and actually defined) "scalar type".  Fun.

Cheers,
  Nick

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


#1844

FromShao Miller <sha0.miller@gmail.com>
Date2013-01-16 10:53 -0500
Message-ID<kd6ie5$hli$1@dont-email.me>
In reply to#1843
On 1/16/2013 09:55, Nick Bowler wrote:
>
> I have a feeling that when the authors wrote "scalar object" in n1570
> 6.5p2 they had something specific in mind, but the term does not appear
> to be defined anywhere in the standard.  The term also is not in the
> index.  Perhaps this was corrected in the final standard which I do not
> have a copy of.
>
> "Scalar object" is also used in 5.1.2.4p14, where context suggests that
> it at least excludes bit-fields.  It appears again in 5.1.2.4p19 with
> context suggesting that it includes objects with atomic types.  It is
> also used a couple times in Annex K, with context suggesting that it
> does not include objects that are elements of arrays.
>
> At the very least, the undefined term "scalar object" appears to
> have absolutely nothing to do with the confusingly similarly-named
> (and actually defined) "scalar type".  Fun.
>

I just assumed it means "object with a scalar type", but I don't know 
for sure.  In this code example, if we are talking about the "region of 
storage," then its declared type is a union type.  If we are talking 
about a sub-object (perhaps corresponding to one of the union members), 
which one are we talking about?

Or maybe the first byte of the object representation of the union (or 
again, of one of its members) is an 'unsigned char'-typed scalar object 
under consideration?  That'd make a lot of sense, because then you could 
modify two members of a structure in an unsequenced fashion, whereas 
that could've been argued as being two modifications to the same object, 
in C99.  But still, it takes a little bit to leap to an 'unsigned char' 
scalar object, when there are no 'unsigned char' effective types hanging 
around.

The Annex K mentions are a bit weird, but I think it's trying to say the 
same sort of thing as pointer arithmetic: A pointer to a scalar is 
treated as pointing into an array of the referenced type, with one 
element, for purposes of bounds-checking.

-- 
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.

Cheerily,"  -- Richard Harter

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


#1845

FromJames Kuyper <jameskuyper@verizon.net>
Date2013-01-16 11:04 -0500
Message-ID<50F6CF92.4090803@verizon.net>
In reply to#1843
On 01/16/2013 09:55 AM, Nick Bowler wrote:
> On Tue, 15 Jan 2013 22:32:27 -0500, Shao Miller wrote:
>> #include <stdio.h>
>>
>>    void func1(void * vp1, void * vp2) {
>>        int * ip;
>>        double * dp;
>>
>>        /* Populate ip and dp? */
>>        if (!vp1 && !vp2) {
>>            func1(&ip, &dp);
>>
>>            /*
>>             * 6.5p2: Unsequenced side effects
>>             * on the same... Scalar?
>>             */
>>            printf("%f\n", (*ip = 42) + (*dp = 3.14));
>>          }
>>
>>        /* Self-called? */
>>        if (vp1 && vp2) {
>>            /* Aliasing shoved down here */
>>            static union {
>>                int i;
>>                double d;
>>              } u;
>>            *(int **) vp1 = &u.i;
>>            *(double **) vp2 = &u.d;
>>          }
>>      }
>>
>>    int main(void) { func1(NULL, NULL); return 0; }
>>
>> Sorry all, I'm puzzled...  This surely yields undefined behaviour, but 
>> why, in C11?  6.5p2 changed from that of C99.  Is it because one of the 
>> '+' operands could establish an effective type before the other?
> 
> I have a feeling that when the authors wrote "scalar object" in n1570
> 6.5p2 they had something specific in mind, but the term does not appear
> to be defined anywhere in the standard.  The term also is not in the
> index.  Perhaps this was corrected in the final standard which I do not
> have a copy of.

A "scalar object" should simply mean an "object of scalar type".

> "Scalar object" is also used in 5.1.2.4p14, where context suggests that
> it at least excludes bit-fields. ...

You're right, and I think that's a mistake. All bit-fields with non-zero
widths are objects which have scalar types.

> ...  It appears again in 5.1.2.4p19 with
> context suggesting that it includes objects with atomic types. ...

Yes, any object with an atomic scalar type would qualify.

>  ... It is
> also used a couple times in Annex K, with context suggesting that it
> does not include objects that are elements of arrays.

Yes, array types are not scalar.

> At the very least, the undefined term "scalar object" appears to
> have absolutely nothing to do with the confusingly similarly-named
> (and actually defined) "scalar type".  Fun.

The only problem I can see with my interpretation is 5.1.2.4p14, which I
think was a mistake. Do you have any other reason for believing that a
"scalar object" means anything other than an "object with scalar type"?

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


#1846

FromNick Bowler <nbowler@draconx.ca>
Date2013-01-16 20:56 +0000
Message-ID<kd745t$mm8$1@dont-email.me>
In reply to#1845
On Wed, 16 Jan 2013 11:04:34 -0500, James Kuyper wrote:
> On 01/16/2013 09:55 AM, Nick Bowler wrote:
>> On Tue, 15 Jan 2013 22:32:27 -0500, Shao Miller wrote:
>>> #include <stdio.h>
>>>
>>>    void func1(void * vp1, void * vp2) {
>>>        int * ip;
>>>        double * dp;
>>>
>>>        /* Populate ip and dp? */
>>>        if (!vp1 && !vp2) {
>>>            func1(&ip, &dp);
>>>
>>>            /*
>>>             * 6.5p2: Unsequenced side effects
>>>             * on the same... Scalar?
>>>             */
>>>            printf("%f\n", (*ip = 42) + (*dp = 3.14));
>>>          }
>>>
>>>        /* Self-called? */
>>>        if (vp1 && vp2) {
>>>            /* Aliasing shoved down here */
>>>            static union {
>>>                int i;
>>>                double d;
>>>              } u;
>>>            *(int **) vp1 = &u.i;
>>>            *(double **) vp2 = &u.d;
>>>          }
>>>      }
>>>
>>>    int main(void) { func1(NULL, NULL); return 0; }
>>>
>>> Sorry all, I'm puzzled...  This surely yields undefined behaviour, but 
>>> why, in C11?  6.5p2 changed from that of C99.  Is it because one of the 
>>> '+' operands could establish an effective type before the other?
>> 
>> I have a feeling that when the authors wrote "scalar object" in n1570
>> 6.5p2 they had something specific in mind, but the term does not appear
>> to be defined anywhere in the standard.  The term also is not in the
>> index.  Perhaps this was corrected in the final standard which I do not
>> have a copy of.
> 
> A "scalar object" should simply mean an "object of scalar type".

Well, "object with scalar type" is clearly an inappropriate definition
for "scalar object".  "Object with atomic, qualified or unqualified
scalar type" would be a bit better, but that definition still seems
inappropriate for the usage in Annex K (see below).  This is exactly
why terms like this need to be defined.

>> "Scalar object" is also used in 5.1.2.4p14, where context suggests that
>> it at least excludes bit-fields. ...
> 
> You're right, and I think that's a mistake. All bit-fields with non-zero
> widths are objects which have scalar types.
> 
>> ...  It appears again in 5.1.2.4p19 with
>> context suggesting that it includes objects with atomic types. ...
> 
> Yes, any object with an atomic scalar type would qualify.

Assuming your "simple" definition is changed as per above, sure.

>>  ... It is also used a couple times in Annex K, with context
>>  suggesting that it does not include objects that are elements of
>>  arrays.
> 
> Yes, array types are not scalar.

I didn't say array types, and neither does Annex K.  I said *elements of
arrays*, which can most certainly be objects with atomic, qualified or
unqualified scalar type.

>> At the very least, the undefined term "scalar object" appears to
>> have absolutely nothing to do with the confusingly similarly-named
>> (and actually defined) "scalar type".  Fun.
> 
> The only problem I can see with my interpretation is 5.1.2.4p14, which I
> think was a mistake. Do you have any other reason for believing that a
> "scalar object" means anything other than an "object with scalar type"?

In addition to what's said above, this still leaves the OP: how are
unions (which most certainly do *not* have atomic, qualified or
unqualified scalar type) to be treated with respect to 6.5p2?  I suspect
the authors intended them to be included, since they *were* covered by
6.5p2 in previous versions of the standard.

Cheers,
  Nick

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


#1849

FromTim Rentsch <txr@alumni.caltech.edu>
Date2013-01-17 13:21 -0800
Message-ID<kfnfw1za4k2.fsf@x-alumni2.alumni.caltech.edu>
In reply to#1846
Nick Bowler <nbowler@draconx.ca> writes:

> On Wed, 16 Jan 2013 11:04:34 -0500, James Kuyper wrote:
>> On 01/16/2013 09:55 AM, Nick Bowler wrote:
>>> On Tue, 15 Jan 2013 22:32:27 -0500, Shao Miller wrote:
>>>> #include <stdio.h>
>>>>
>>>>    void func1(void * vp1, void * vp2) {
>>>>        int * ip;
>>>>        double * dp;
>>>>
>>>>        /* Populate ip and dp? */
>>>>        if (!vp1 && !vp2) {
>>>>            func1(&ip, &dp);
>>>>
>>>>            /*
>>>>             * 6.5p2: Unsequenced side effects
>>>>             * on the same... Scalar?
>>>>             */
>>>>            printf("%f\n", (*ip = 42) + (*dp = 3.14));
>>>>          }
>>>>
>>>>        /* Self-called? */
>>>>        if (vp1 && vp2) {
>>>>            /* Aliasing shoved down here */
>>>>            static union {
>>>>                int i;
>>>>                double d;
>>>>              } u;
>>>>            *(int **) vp1 = &u.i;
>>>>            *(double **) vp2 = &u.d;
>>>>          }
>>>>      }
>>>>
>>>>    int main(void) { func1(NULL, NULL); return 0; }
>>>>
>>>> Sorry all, I'm puzzled...  This surely yields undefined behaviour, but 
>>>> why, in C11?  6.5p2 changed from that of C99.  Is it because one of the 
>>>> '+' operands could establish an effective type before the other?
>>> 
>>> I have a feeling that when the authors wrote "scalar object" in n1570
>>> 6.5p2 they had something specific in mind, but the term does not appear
>>> to be defined anywhere in the standard.  The term also is not in the
>>> index.  Perhaps this was corrected in the final standard which I do not
>>> have a copy of.
>> 
>> A "scalar object" should simply mean an "object of scalar type".
>
> Well, "object with scalar type" is clearly an inappropriate definition
> for "scalar object".  "Object with atomic, qualified or unqualified
> scalar type" would be a bit better, but that definition still seems
> inappropriate for the usage in Annex K (see below).  This is exactly
> why terms like this need to be defined.
>
>>> "Scalar object" is also used in 5.1.2.4p14, where context suggests that
>>> it at least excludes bit-fields. ...
>> 
>> You're right, and I think that's a mistake. All bit-fields with non-zero
>> widths are objects which have scalar types.
>> 
>>> ...  It appears again in 5.1.2.4p19 with
>>> context suggesting that it includes objects with atomic types. ...
>> 
>> Yes, any object with an atomic scalar type would qualify.
>
> Assuming your "simple" definition is changed as per above, sure.
>
>>>  ... It is also used a couple times in Annex K, with context
>>>  suggesting that it does not include objects that are elements of
>>>  arrays.
>> 
>> Yes, array types are not scalar.
>
> I didn't say array types, and neither does Annex K.  I said *elements of
> arrays*, which can most certainly be objects with atomic, qualified or
> unqualified scalar type.

The idea here isn't that hard to understand.  If the same region
of memory is modified more than once, or modfied once and read at
least once, the behavior is undefined (when sequencing between a
modification and another access is not guaranteed).  The only
challenge is to define a term that codifies "the same region of
memory" accurately, unambiguously, and exactly.

The wording used in C89 (and left unchanged in C99) had a problem
with ambiguity, by referring to "an object".  If we have a struct
object s with members i and j, is 's.i++ * s.j++' in violation of
the "same object" condition or not?  Obviously it wasn't meant to
be.  To fix that problem, the wording was changed to use the
phrase "scalar object".  The term may not be clearly defined, but
the idea is simple - something that is always dealt with as a
whole, not having any identifiable subcomponents that can be
accessed without necessarily having to access their "enclosing"
object.  This makes structs, unions, and arrays be non-scalar
objects.  A scalar object is one that is accessed using a scalar
type, or a qualified version of a scalar type (where here the
_Atomic qualifier is meant to be included).  There may be some
stuff related to _Atomic that needs more careful attention (I
haven't yet read about _Atomic very carefully), but that doesn't
change the basic idea.  All that's left is coming up with
suitable phrasing (and that may not be trivial, but it shouldn't
interfere with understanding).  Any access of a struct or union
type is understood to be an access of each of the component
objects in the struct or union, recursively, down to the point
where scalar objects are reached.  Similarly, an access of a
scalar object is understood to be an access of each of the
character objects that make up the memory of the scalar object.
Bitfields are discussed below.


>>> At the very least, the undefined term "scalar object" appears to
>>> have absolutely nothing to do with the confusingly similarly-named
>>> (and actually defined) "scalar type".  Fun.
>> 
>> The only problem I can see with my interpretation is 5.1.2.4p14, which I
>> think was a mistake. Do you have any other reason for believing that a
>> "scalar object" means anything other than an "object with scalar type"?
>
> In addition to what's said above, this still leaves the OP: how are
> unions (which most certainly do *not* have atomic, qualified or
> unqualified scalar type) to be treated with respect to 6.5p2?  I suspect
> the authors intended them to be included, since they *were* covered by
> 6.5p2 in previous versions of the standard.

That assertion is debatable.  However, even if the wording used
in C89/C99 is taken to cover unions, that happened only by
accident, because the same argument could be used with structs,
and clearly it was not intended that two different members of
a struct would be in conflict if modified in the same expression.
Furthermore it's easy to find an example where parts of a union
can be modified separately in safety, eg,

  union {
    long  x[100];
    short y[ sizeof (long[100]) / sizeof (short) ];
  } u = {0};

  u.x[10]++ * u.y[5]++;  /* assume sizeof (long) >= sizeof (short) */

The scalar object u.x[10] is not the same scalar object as
u.y[5], so this expression is safe.  (To be thorough, I should
include a proviso that this code is run on a platform where
all-bits-zero is the only representation of zero for both long
and short, so the initialization produces object representation
suitable for both members.)

Getting back to bitfields..  before C11, an access of a bitfield
is supposed to behave like an access to any other scalar member.
As long as bitfields are accessed as members (and there is no
funny business going on with some other aliased access), it's okay
to modify one bitfield and access another (or another non-bitfield
member), and vice versa.  Surely if that were not true the
Standard would say something to help delineate where such things
might cause problems, at least in a footnore or example.  AFAIK
the Standard contains no such premonishment.

When there is aliasing things are more complicated.  Adjacent
bitfields are packed together in an "addressable unit" of unknown
size, may take up either less than or more than one char's worth
of memory, and may overlap char boundaries (which I suppose is
obvious if they can take more than a char's worth of space).  When
working on a bitfield and another member of the same struct,
implementations are obliged to keep things straight;  potential
conflicts are easy to anticipate and not too hard to avoid.
However, storing a value into a bitfield can involve modifying
memory beyond that occupied by the bitfield itself, so a larger
area (eg, the "addressable unit" into which the bitfield is
packed) may need to be stored.  When an aliased access overlaps
this larger area of memory, even though the aliased access
memory area doesn't overlap the bitfield itself, there still may
be some interaction between the two accesses.  Which "object" is
being modified for the purpose of considering 6.5p2?  I'm not
sure there is consensus on this question, which is to say I
wouldn't be surprised to find different implementations take
different positions about what the answer is for that.  It
would be good if this ambiguity were clarified (and it may be
for all I know -- certainly there are DR's and other documents
I haven't read that may have addressed it).

Returning to C11..  Now we have threads, and the rules for memory
access are different intra-thread and inter-thread.  In the
inter-thread case, new passages make it clear that bitfields are
(or may be) accessed in units larger than just the bitfield
itself, and that plays into the possibility of memory conflicts.
The distinction shows up in 5.1.2.4 p14, but in fact is presaged
in 3.14, defining 'memory location'.  Because 'scalar object' and
'bit-field' are used as adjectives modifying 'M' (presumably a
stand-in for 'memory location'), it isn't clear if this usage is
really in conflict with the usage in 6.5 p2, or if it just seems
that way because of some linguistic distinction in the two uses.
In any case, if there is an actual inconsistency and not just an
apparent one, surely that is just an oversight, caused by needing
to express criteria under the new inter-thread rules rather than
the old (intra-thread) ones.

Does that all make sense?  Is there something important that was
left out?

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


#1850

FromShao Miller <sha0.miller@gmail.com>
Date2013-01-17 17:50 -0500
Message-ID<kd9v6r$ge3$1@dont-email.me>
In reply to#1849
On 1/17/2013 16:21, Tim Rentsch wrote:
> Furthermore it's easy to find an example where parts of a union
> can be modified separately in safety, eg,
>
>    union {
>      long  x[100];
>      short y[ sizeof (long[100]) / sizeof (short) ];
>    } u = {0};
>
>    u.x[10]++ * u.y[5]++;  /* assume sizeof (long) >= sizeof (short) */
>
> The scalar object u.x[10] is not the same scalar object as
> u.y[5], so this expression is safe.  (To be thorough, I should
> include a proviso that this code is run on a platform where
> all-bits-zero is the only representation of zero for both long
> and short, so the initialization produces object representation
> suitable for both members.)
>

It can be (and has been) argued that this is a violation of 6.5p7.  In 
fact, WG14 hasn't reached consensus.  (I asked.)

-- 
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.

Cheerily,"  -- Richard Harter

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


#1856

FromTim Rentsch <txr@alumni.caltech.edu>
Date2013-01-18 11:25 -0800
Message-ID<kfntxqe8faa.fsf@x-alumni2.alumni.caltech.edu>
In reply to#1850
Shao Miller <sha0.miller@gmail.com> writes:

> On 1/17/2013 16:21, Tim Rentsch wrote:
>> Furthermore it's easy to find an example where parts of a union
>> can be modified separately in safety, eg,
>>
>>    union {
>>      long  x[100];
>>      short y[ sizeof (long[100]) / sizeof (short) ];
>>    } u = {0};
>>
>>    u.x[10]++ * u.y[5]++;  /* assume sizeof (long) >= sizeof (short) */
>>
>> The scalar object u.x[10] is not the same scalar object as
>> u.y[5], so this expression is safe.  (To be thorough, I should
>> include a proviso that this code is run on a platform where
>> all-bits-zero is the only representation of zero for both long
>> and short, so the initialization produces object representation
>> suitable for both members.)
>>
>
> It can be (and has been) argued that this is a violation of 6.5p7.  In
> fact, WG14 hasn't reached consensus.  (I asked.)

Even supposing that were true, it's obviously irrelevant to the
point I was making.  And besides, it's perfectly easy to
construct an equivalent example that clearly doesn't run afoul of
effective type limitations, simply by using character types.

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


#1857

FromShao Miller <sha0.miller@gmail.com>
Date2013-01-18 15:07 -0500
Message-ID<kdca2j$m5n$1@dont-email.me>
In reply to#1856
On 1/18/2013 14:25, Tim Rentsch wrote:
> Shao Miller <sha0.miller@gmail.com> writes:
>
>> On 1/17/2013 16:21, Tim Rentsch wrote:
>>> Furthermore it's easy to find an example where parts of a union
>>> can be modified separately in safety, eg,
>>>
>>>     union {
>>>       long  x[100];
>>>       short y[ sizeof (long[100]) / sizeof (short) ];
>>>     } u = {0};
>>>
>>>     u.x[10]++ * u.y[5]++;  /* assume sizeof (long) >= sizeof (short) */
>>>
>>> The scalar object u.x[10] is not the same scalar object as
>>> u.y[5], so this expression is safe.  (To be thorough, I should
>>> include a proviso that this code is run on a platform where
>>> all-bits-zero is the only representation of zero for both long
>>> and short, so the initialization produces object representation
>>> suitable for both members.)
>>>
>>
>> It can be (and has been) argued that this is a violation of 6.5p7.  In
>> fact, WG14 hasn't reached consensus.  (I asked.)
>
> Even supposing that were true, it's obviously irrelevant to the
> point I was making.  And besides, it's perfectly easy to
> construct an equivalent example that clearly doesn't run afoul of
> effective type limitations, simply by using character types.
>

Agreed.  I don't dispute "it's easy to find..." and I enjoyed your 
post's explanation of scalar accesses.  Thanks!

-- 
- Shao Miller
--
"Thank you for the kind words; those are the kind of words I like to hear.

Cheerily,"  -- Richard Harter

[toc] | [prev] | [standalone]


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


csiph-web