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


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

Union test for endianess

Started byBhasker Penta <bskdsp@gmail.com>
First post2011-06-16 20:16 -0700
Last post2011-06-20 12:22 -0700
Articles 20 on this page of 50 — 19 participants

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


Contents

  Union test for endianess Bhasker Penta <bskdsp@gmail.com> - 2011-06-16 20:16 -0700
    Re: Union test for endianess Ian Collins <ian-news@hotmail.com> - 2011-06-17 15:36 +1200
      Re: Union test for endianess Willem <willem@toad.stack.nl> - 2011-06-17 14:13 +0000
        Re: Union test for endianess Joe Wright <joewwright@comcast.net> - 2011-06-17 14:00 -0400
          Re: Union test for endianess Jorgen Grahn <grahn+nntp@snipabacken.se> - 2011-06-19 19:25 +0000
    Re: Union test for endianess China Blue Angels <chine.bleu@yahoo.com> - 2011-06-16 20:54 -0700
      Re: Union test for endianess Willem <willem@toad.stack.nl> - 2011-06-17 14:14 +0000
        Re: Union test for endianess James Kuyper <jameskuyper@verizon.net> - 2011-06-17 10:28 -0400
          Re: Union test for endianess Keith Thompson <kst-u@mib.org> - 2011-06-17 10:54 -0700
        Re: Union test for endianess Shao Miller <sha0.miller@gmail.com> - 2011-06-17 10:35 -0500
        Re: Union test for endianess "J. J. Farrell" <jjf@bcs.org.uk> - 2011-06-18 01:50 +0100
    Re: Union test for endianess China Blue Angels <chine.bleu@yahoo.com> - 2011-06-16 21:00 -0700
      Re: Union test for endianess Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-06-17 12:09 +0100
    Re: Union test for endianess Shao Miller <sha0.miller@gmail.com> - 2011-06-17 00:50 -0500
      Re: Union test for endianess Bhasker Penta <bskdsp@gmail.com> - 2011-06-16 23:17 -0700
        Re: Union test for endianess Shao Miller <sha0.miller@gmail.com> - 2011-06-17 03:01 -0500
          Re: Union test for endianess Shao Miller <sha0.miller@gmail.com> - 2011-06-17 13:33 -0500
            Re: Union test for endianess James Kuyper <jameskuyper@verizon.net> - 2011-06-18 09:18 -0400
            Re: Union test for endianess Shao Miller <sha0.miller@gmail.com> - 2011-06-19 17:22 -0500
            Re: Union test for endianess Tim Rentsch <txr@alumni.caltech.edu> - 2011-06-19 16:24 -0700
          Re: Union test for endianess Bhasker Penta <bskdsp@gmail.com> - 2011-06-18 01:08 -0700
          Re: Union test for endianess Tim Rentsch <txr@alumni.caltech.edu> - 2011-06-19 15:52 -0700
    Re: Union test for endianess James Kuyper <jameskuyper@verizon.net> - 2011-06-17 09:32 -0400
      Re: Union test for endianess James Kuyper <jameskuyper@verizon.net> - 2011-06-17 09:52 -0400
        Re: Union test for endianess Bhasker Penta <bskdsp@gmail.com> - 2011-06-17 07:13 -0700
          Re: Union test for endianess James Kuyper <jameskuyper@verizon.net> - 2011-06-17 10:31 -0400
      Re: Union test for endianess "christian.bau" <christian.bau@cbau.wanadoo.co.uk> - 2011-06-17 15:57 -0700
        Re: Union test for endianess Keith Thompson <kst-u@mib.org> - 2011-06-17 16:42 -0700
          Re: Union test for endianess James Waldby <not@valid.invalid> - 2011-06-18 02:53 +0000
            Re: Union test for endianess James Kuyper <jameskuyper@verizon.net> - 2011-06-17 23:59 -0400
              Re: Union test for endianess James Waldby <not@valid.invalid> - 2011-06-18 14:45 +0000
                Re: Union test for endianess James Kuyper <jameskuyper@verizon.net> - 2011-06-18 11:08 -0400
                Re: Union test for endianess cri@tiac.net (Richard Harter) - 2011-06-18 19:47 +0000
                  Re: Union test for endianess James Waldby <not@valid.invalid> - 2011-06-18 23:15 +0000
                    Re: Union test for endianess James Kuyper <jameskuyper@verizon.net> - 2011-06-18 22:42 -0400
                Re: Union test for endianess Jens <jens.gustedt@gmail.com> - 2011-06-19 07:41 -0700
                Re: Union test for endianess Roberto Waltman <usenet@rwaltman.com> - 2011-06-22 11:25 -0400
                  Re: Union test for endianess James Kuyper <jameskuyper@verizon.net> - 2011-06-22 11:40 -0400
                    Re: Union test for endianess James Waldby <not@valid.invalid> - 2011-06-22 21:42 +0000
        Re: Union test for endianess James Kuyper <jameskuyper@verizon.net> - 2011-06-17 21:18 -0400
    Re: Union test for endianess falk@rahul.net (Edward A. Falk) - 2011-06-17 20:50 +0000
    Re: Union test for endianess "Morris Keesan" <mkeesan@post.harvard.edu> - 2011-06-18 10:42 -0400
      Re: Union test for endianess Ben Bacarisse <ben.usenet@bsb.me.uk> - 2011-06-18 22:55 +0100
        Re: Union test for endianess "Morris Keesan" <mkeesan@post.harvard.edu> - 2011-06-19 21:14 -0400
    Re: Union test for endianess Jens <jens.gustedt@gmail.com> - 2011-06-19 07:46 -0700
      Re: Union test for endianess Tim Rentsch <txr@alumni.caltech.edu> - 2011-06-19 16:14 -0700
      Re: Union test for endianess Shao Miller <sha0.miller@gmail.com> - 2011-06-19 20:24 -0500
        Re: Union test for endianess Jens <jens.gustedt@gmail.com> - 2011-06-20 00:31 -0700
          Re: Union test for endianess Shao Miller <sha0.miller@gmail.com> - 2011-06-20 04:33 -0500
          Re: Union test for endianess Tim Rentsch <txr@alumni.caltech.edu> - 2011-06-20 12:22 -0700

Page 1 of 3  [1] 2 3  Next page →


#6215 — Union test for endianess

FromBhasker Penta <bskdsp@gmail.com>
Date2011-06-16 20:16 -0700
SubjectUnion test for endianess
Message-ID<f19541de-213c-4744-b712-92f20a3ad294@d26g2000prn.googlegroups.com>
One way to test for endianess is to use a union:

void endianTest()
{
    union     // sizeof(int) == 4
    {
        int i;
        char ch[4];
    } U;

    U.i=0x12345678; // writing to int member
    if ( U.ch[0]==0x78 )   // reading from char member
        puts("\nLittle endian");
    else
        puts("\nBig endian");
}

Writing to one member of a union and reading from another member is
implementation defined(K & R). This example is used for testing
endianess @ c-faq.com. I know that gcc allows this. Is the above
snippet to test for endianess legal C or C++?

[toc] | [next] | [standalone]


#6217

FromIan Collins <ian-news@hotmail.com>
Date2011-06-17 15:36 +1200
Message-ID<9600etFu2qU3@mid.individual.net>
In reply to#6215
On 06/17/11 03:31 PM, Stefan Ram wrote:
> Bhasker Penta<bskdsp@gmail.com>  writes:
>> U.i=0x12345678; // writing to int member
>> if ( U.ch[0]==0x78 )   // reading from char member
>> Writing to one member of a union and reading from another member is
>> implementation defined(K&  R).
>
>        »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«
>                     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
>      ISO/IEC 9899:1999 (E), 6.2.6.1#7
>
How is that relevant to the question, which assumes sizeof(int) == 4?

>    One also might cast a pointer to int into a pointer to char[],
>    but I assume, dereferencing this might also give unspecified
>    values in the best case or might result in undefined behavior
>    in the worst case?

Do what? How is that relevant to, well anything?

>    Endianess is an implementation detail of a higher
>    programming language that the language wants to hide from
>    you (information hiding), because usually one does not need
>    to know it. One even can serialize and deserialize in either
>    a portable or an implementation specific manner without
>    knowing this.

Who ever writes the serialisation code does need to know.  If you need 
to know the endianess, you are probably writing serialisation code!

-- 
Ian Collins

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


#6236

FromWillem <willem@toad.stack.nl>
Date2011-06-17 14:13 +0000
Message-ID<slrnivmo8n.15tq.willem@toad.stack.nl>
In reply to#6217
Ian Collins wrote:
) On 06/17/11 03:31 PM, Stefan Ram wrote:
)>    Endianess is an implementation detail of a higher
)>    programming language that the language wants to hide from
)>    you (information hiding), because usually one does not need
)>    to know it. One even can serialize and deserialize in either
)>    a portable or an implementation specific manner without
)>    knowing this.
)
) Who ever writes the serialisation code does need to know.  If you need 
) to know the endianess, you are probably writing serialisation code!

He just *specifically* stated that who ever writes the serialisation
code *DOES NOT NEED* to know, so your statement does not make sense.


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

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


#6285

FromJoe Wright <joewwright@comcast.net>
Date2011-06-17 14:00 -0400
Message-ID<f6udncLSe4HcC2bQnZ2dnUVZ_u6dnZ2d@giganews.com>
In reply to#6236
On 6/17/2011 10:13, Willem wrote:
> Ian Collins wrote:
> ) On 06/17/11 03:31 PM, Stefan Ram wrote:
> )>     Endianess is an implementation detail of a higher
> )>     programming language that the language wants to hide from
> )>     you (information hiding), because usually one does not need
> )>     to know it. One even can serialize and deserialize in either
> )>     a portable or an implementation specific manner without
> )>     knowing this.
> )
> ) Who ever writes the serialisation code does need to know.  If you need
> ) to know the endianess, you are probably writing serialisation code!
>
> He just *specifically* stated that who ever writes the serialisation
> code *DOES NOT NEED* to know, so your statement does not make sense.
>
>
> SaSW, Willem

I'm not sure what serialisation code is but I don't think endianness needs 
to be known. I can write hton and ntoh routines that don't care. But if I 
did want to know for some reason..

   int i = 1;
   int big = *(char*)&i == 0;

..should do the trick most of the time.

-- 
Joe Wright
"If you rob Peter to pay Paul you can depend on the support of Paul."

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


#6463

FromJorgen Grahn <grahn+nntp@snipabacken.se>
Date2011-06-19 19:25 +0000
Message-ID<slrnivsj9s.gtj.grahn+nntp@frailea.sa.invalid>
In reply to#6285
On Fri, 2011-06-17, Joe Wright wrote:
> On 6/17/2011 10:13, Willem wrote:
>> Ian Collins wrote:
>> ) On 06/17/11 03:31 PM, Stefan Ram wrote:
>> )>     Endianess is an implementation detail of a higher
>> )>     programming language that the language wants to hide from
>> )>     you (information hiding), because usually one does not need
>> )>     to know it. One even can serialize and deserialize in either
>> )>     a portable or an implementation specific manner without
>> )>     knowing this.
>> )
>> ) Who ever writes the serialisation code does need to know.  If you need
>> ) to know the endianess, you are probably writing serialisation code!
>>
>> He just *specifically* stated that who ever writes the serialisation
>> code *DOES NOT NEED* to know, so your statement does not make sense.
>>
>>
>> SaSW, Willem
>
> I'm not sure what serialisation code is but I don't think endianness needs 
> to be known. I can write hton and ntoh routines that don't care.

Plus, if you're doing serialization into/from sequences of octets, you
don't even need POSIX-line htons/htonl.

  uint32_t n;
  ...
  uint8_t msb = n >> 24;

is predictable, yet not endianness-aware.

/Jorgen

-- 
  // Jorgen Grahn <grahn@  Oo  o.   .  .
\X/     snipabacken.se>   O  o   .

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


#6218

FromChina Blue Angels <chine.bleu@yahoo.com>
Date2011-06-16 20:54 -0700
Message-ID<chine.bleu-19C0F6.20544016062011@news.eternal-september.org>
In reply to#6215
In article <union-20110617051812@ram.dialup.fu-berlin.de>,
 ram@zedat.fu-berlin.de (Stefan Ram) wrote:

> Bhasker Penta <bskdsp@gmail.com> writes:
> >U.i=0x12345678; // writing to int member
> >if ( U.ch[0]==0x78 )   // reading from char member
> >Writing to one member of a union and reading from another member is
> >implementation defined(K & R).
> 
>       »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«
>                    ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

All the bytes of i correspond to bytes of ch, and all the bytes of ch correspond 
to bytes of i.

    union     // sizeof(int) == 4
    {
        int i;
        char ch[4];
    } U;

-- 
I remember finding out about you,  |              I survived XYZZY-Day.
Everyday my mind is all around you,|     I'm whoever you want me to be.
Looking out from my lonely room    |Annoying Usenet one post at a time.
Day after day.                     |  At least I can stay in character.

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


#6237

FromWillem <willem@toad.stack.nl>
Date2011-06-17 14:14 +0000
Message-ID<slrnivmoah.15tq.willem@toad.stack.nl>
In reply to#6218
China Blue Angels wrote:
) In article <union-20110617051812@ram.dialup.fu-berlin.de>,
)  ram@zedat.fu-berlin.de (Stefan Ram) wrote:
)>       ?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?
)>                    ??????????????????
)
) All the bytes of i correspond to bytes of ch, and all the bytes of ch correspond 
) to bytes of i.
)
)     union     // sizeof(int) == 4
)     {
)         int i;
)         char ch[4];
)     } U;

Or not.  It's UNSPECIFIED.


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

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


#6238

FromJames Kuyper <jameskuyper@verizon.net>
Date2011-06-17 10:28 -0400
Message-ID<itfoav$6cb$1@dont-email.me>
In reply to#6237
On 06/17/2011 10:14 AM, Willem wrote:
> China Blue Angels wrote:
> ) In article <union-20110617051812@ram.dialup.fu-berlin.de>,
> )  ram@zedat.fu-berlin.de (Stefan Ram) wrote:
> )>       ?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?
> )>                    ??????????????????
> )
> ) All the bytes of i correspond to bytes of ch, and all the bytes of ch correspond 
> ) to bytes of i.
> )
> )     union     // sizeof(int) == 4
> )     {
> )         int i;
> )         char ch[4];
> )     } U;
> 
> Or not.  It's UNSPECIFIED.

As far as I can tell, every single byte of the object representation of
U that correspond to U.ch, is also a byte that corresponds to U.i (and
vice versa). There are no relevant bytes that take on unspecified
values. Are you suggesting otherwise? If so, on what grounds?
-- 
James Kuyper

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


#6284

FromKeith Thompson <kst-u@mib.org>
Date2011-06-17 10:54 -0700
Message-ID<lnaadg1gz1.fsf@nuthaus.mib.org>
In reply to#6238
James Kuyper <jameskuyper@verizon.net> writes:
> On 06/17/2011 10:14 AM, Willem wrote:
>> China Blue Angels wrote:
>> ) In article <union-20110617051812@ram.dialup.fu-berlin.de>,
>> )  ram@zedat.fu-berlin.de (Stefan Ram) wrote:
>> )>       ?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?
>> )>                    ??????????????????
>> )
>> ) All the bytes of i correspond to bytes of ch, and all the bytes of ch correspond 
>> ) to bytes of i.
>> )
>> )     union     // sizeof(int) == 4
>> )     {
>> )         int i;
>> )         char ch[4];
>> )     } U;
>> 
>> Or not.  It's UNSPECIFIED.
>
> As far as I can tell, every single byte of the object representation of
> U that correspond to U.ch, is also a byte that corresponds to U.i (and
> vice versa). There are no relevant bytes that take on unspecified
> values. Are you suggesting otherwise? If so, on what grounds?

And since the representations of int and char are implementation-defined
(meaning the implementation must document them), you can tell, given the
implementation's documentation, what values are stored in ch when you
store a value in i (unless there are padding bits).

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <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"

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


#6240

FromShao Miller <sha0.miller@gmail.com>
Date2011-06-17 10:35 -0500
Message-ID<itfooq$9gi$1@dont-email.me>
In reply to#6237
On 6/17/2011 9:14 AM, Willem wrote:
> China Blue Angels wrote:
> ) In article<union-20110617051812@ram.dialup.fu-berlin.de>,
> )  ram@zedat.fu-berlin.de (Stefan Ram) wrote:
> )>        ?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?
> )>                     ??????????????????
> )
> ) All the bytes of i correspond to bytes of ch, and all the bytes of ch correspond
> ) to bytes of i.
> )
> )     union     // sizeof(int) == 4
> )     {
> )         int i;
> )         char ch[4];
> )     } U;
>
> Or not.  It's UNSPECIFIED.

What is "it?"  The behaviour?  The values for each element of 'ch'? 
Given that 'sizeof (int) == 4', the 'ch' array member exactly overlaps 
the 'i' member.  I don't follow you.

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


#6323

From"J. J. Farrell" <jjf@bcs.org.uk>
Date2011-06-18 01:50 +0100
Message-ID<itgsp9$391$1@dont-email.me>
In reply to#6237
Willem wrote:
> China Blue Angels wrote:
> ) In article <union-20110617051812@ram.dialup.fu-berlin.de>,
> )  ram@zedat.fu-berlin.de (Stefan Ram) wrote:
> )>       ?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?
> )>                    ??????????????????
> )
> ) All the bytes of i correspond to bytes of ch, and all the bytes of ch correspond 
> ) to bytes of i.
> )
> )     union     // sizeof(int) == 4
> )     {
> )         int i;
> )         char ch[4];
> )     } U;
> 
> Or not.  It's UNSPECIFIED.

What do you mean? The OP specifies that in this case sizeof(int) is 4. 
In that case all the bytes which correspond to member i also correspond 
to member ch. What do you believe to be unspecified?

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


#6219

FromChina Blue Angels <chine.bleu@yahoo.com>
Date2011-06-16 21:00 -0700
Message-ID<chine.bleu-835811.21003916062011@news.eternal-september.org>
In reply to#6215
In article <f19541de-213c-4744-b712-92f20a3ad294@d26g2000prn.googlegroups.com>,
 Bhasker Penta <bskdsp@gmail.com> wrote:

> One way to test for endianess is to use a union:
> 
> void endianTest()
> {
>     union     // sizeof(int) == 4
>     {
>         int i;
>         char ch[4];
>     } U;
> 
>     U.i=0x12345678; // writing to int member
>     if ( U.ch[0]==0x78 )   // reading from char member
>         puts("\nLittle endian");
>     else
>         puts("\nBig endian");
> }
> 
> Writing to one member of a union and reading from another member is
> implementation defined(K & R). This example is used for testing
> endianess @ c-faq.com. I know that gcc allows this. Is the above
> snippet to test for endianess legal C or C++?

You can use casts to avoid variables.

    #define X (((union{int i; char ch[4];}){.i=0x12345678}).ch[0])
    #define littleEndian (X==0x78)
    #define bigEndian (X==0x01)

-- 
I remember finding out about you,  |              I survived XYZZY-Day.
Everyday my mind is all around you,|     I'm whoever you want me to be.
Looking out from my lonely room    |Annoying Usenet one post at a time.
Day after day.                     |  At least I can stay in character.

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


#6229

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2011-06-17 12:09 +0100
Message-ID<0.0167e5347a17543f93aa.20110617120946BST.87k4ck7lz9.fsf@bsb.me.uk>
In reply to#6219
China Blue Angels <chine.bleu@yahoo.com> writes:

> In article <f19541de-213c-4744-b712-92f20a3ad294@d26g2000prn.googlegroups.com>,
>  Bhasker Penta <bskdsp@gmail.com> wrote:
>> One way to test for endianess is to use a union:
>> 
>> void endianTest()
>> {
>>     union     // sizeof(int) == 4
>>     {
>>         int i;
>>         char ch[4];
>>     } U;
>> 
>>     U.i=0x12345678; // writing to int member
>>     if ( U.ch[0]==0x78 )   // reading from char member
>>         puts("\nLittle endian");
>>     else
>>         puts("\nBig endian");
>> }
<snip>

> You can use casts to avoid variables.
>
>     #define X (((union{int i; char ch[4];}){.i=0x12345678}).ch[0])
>     #define littleEndian (X==0x78)
>     #define bigEndian (X==0x01)

It's probably worth pointing out that this is (a) C99 and (b) has no
casts!

Since all that's needed is a test for two of the possible byte orders,
I'd avoid using a value that might not be a valid int:

  #define X (((union{int i; char ch[sizeof(int)];}){.i=1}).ch[0])

The tests then become X and !X (so I'd use some other name).

-- 
Ben.

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


#6220

FromShao Miller <sha0.miller@gmail.com>
Date2011-06-17 00:50 -0500
Message-ID<iteme0$3va$1@dont-email.me>
In reply to#6215
On 6/16/2011 10:16 PM, Bhasker Penta wrote:
> One way to test for endianess is to use a union:
>
> void endianTest()
> {
>      union     // sizeof(int) == 4
>      {
>          int i;
>          char ch[4];
>      } U;
>
>      U.i=0x12345678; // writing to int member
>      if ( U.ch[0]==0x78 )   // reading from char member
>          puts("\nLittle endian");
>      else
>          puts("\nBig endian");
> }
>

Please note that

One possible way to help to ensure that 'sizeof (int) == 4' and that you 
have 8-bit bytes is to:

   #define TT_ASSERT(message, test) \
     typedef char (message)[(test) ? 1 : -1]

   TT_ASSERT(INT_IS_NOT_4_BYTES, sizeof (int) == 4);
   TT_ASSERT(NOT_8_BIT_BYTE, CHAR_BIT == 8);

> Writing to one member of a union and reading from another member is
> implementation defined(K&  R).

As far as I know, if 'sizeof (int) == 4' as shown, you can certainly 
read from each element of the 'U.ch' array.  C doesn't guarantee that 
'sizeof (int) == 4', of course.

Combined with the 'TT_ASSERT's above, you could have your union as:

   union {
       unsigned int i;
       unsigned char ch[sizeof (unsigned int)];
     } U;

(Note that the use of 'unsigned' attempts to avoid any potential sign 
bit complications; the 'TT_ASSERT' might be better off matching, too.)

> This example is used for testing
> endianess @ c-faq.com. I know that gcc allows this. Is the above
> snippet to test for endianess legal C or C++?

If you know that the implementation definitely uses an 8-bit byte, a 
4-byte 'int', and that there are no padding bits and that '0x12345678' 
is within the range of values for 'int', then I'd say yes for "legal C". :)

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


#6221

FromBhasker Penta <bskdsp@gmail.com>
Date2011-06-16 23:17 -0700
Message-ID<18896aaa-106d-4a43-95bb-a08e13676be2@x38g2000pri.googlegroups.com>
In reply to#6220
On Jun 17, 10:50 am, Shao Miller <sha0.mil...@gmail.com> wrote:
> On 6/16/2011 10:16 PM, Bhasker Penta wrote:
>
>
>
>
>
> > One way to test for endianess is to use a union:
>
> > void endianTest()
> > {
> >      union     // sizeof(int) == 4
> >      {
> >          int i;
> >          char ch[4];
> >      } U;
>
> >      U.i=0x12345678; // writing to int member
> >      if ( U.ch[0]==0x78 )   // reading from char member
> >          puts("\nLittle endian");
> >      else
> >          puts("\nBig endian");
> > }
>
> Please note that
>
> One possible way to help to ensure that 'sizeof (int) == 4' and that you
> have 8-bit bytes is to:
>
>    #define TT_ASSERT(message, test) \
>      typedef char (message)[(test) ? 1 : -1]
>
>    TT_ASSERT(INT_IS_NOT_4_BYTES, sizeof (int) == 4);
>    TT_ASSERT(NOT_8_BIT_BYTE, CHAR_BIT == 8);
>
> > Writing to one member of a union and reading from another member is
> > implementation defined(K&  R).
>
> As far as I know, if 'sizeof (int) == 4' as shown, you can certainly
> read from each element of the 'U.ch' array.  C doesn't guarantee that
> 'sizeof (int) == 4', of course.
>
> Combined with the 'TT_ASSERT's above, you could have your union as:
>
>    union {
>        unsigned int i;
>        unsigned char ch[sizeof (unsigned int)];
>      } U;
>
> (Note that the use of 'unsigned' attempts to avoid any potential sign
> bit complications; the 'TT_ASSERT' might be better off matching, too.)
>
> > This example is used for testing
> > endianess @ c-faq.com. I know that gcc allows this. Is the above
> > snippet to test for endianess legal C or C++?
>
> If you know that the implementation definitely uses an 8-bit byte, a
> 4-byte 'int', and that there are no padding bits and that '0x12345678'
> is within the range of values for 'int', then I'd say yes for "legal C". :)

> If you know that the implementation definitely uses an 8-bit byte, a
> 4-byte 'int', and that there are no padding bits and that '0x12345678'
> is within the range of values for 'int', then I'd say yes for "legal C". :)

At least on my machine (Windows 7 64 bit) sizeof(int)==4,
sizeof(char)==1 and '0x12345678' is within 'int' limit. But the fact
is we are writing to int member and reading from (different) char
member. That doesn't go well with union rules. If it is legal in C
language to reinterpret the content of any object as a char array (or
char pointer), then I believe above snippet is technically correct C
code(I may be wrong).
Eg.
   int i=0x12345678;    //  sizeof(int) == 4
    char *p=(char *)&i;
    if(*p==0x78)           // reinterpreting int i through a char
pointer
        puts("Little Endian");
    else
        puts("Big Endian");

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


#6224

FromShao Miller <sha0.miller@gmail.com>
Date2011-06-17 03:01 -0500
Message-ID<iteu3o$8ll$1@dont-email.me>
In reply to#6221
On 6/17/2011 1:17 AM, Bhasker Penta wrote:
> On Jun 17, 10:50 am, Shao Miller<sha0.mil...@gmail.com>  wrote:
>> On 6/16/2011 10:16 PM, Bhasker Penta wrote:
>>
>>
>>
>>
>>
>>> One way to test for endianess is to use a union:
>>
>>> void endianTest()
>>> {
>>>       union     // sizeof(int) == 4
>>>       {
>>>           int i;
>>>           char ch[4];
>>>       } U;
>>
>>>       U.i=0x12345678; // writing to int member
>>>       if ( U.ch[0]==0x78 )   // reading from char member
>>>           puts("\nLittle endian");
>>>       else
>>>           puts("\nBig endian");
>>> }
>>
>> Please note that
>>
>> One possible way to help to ensure that 'sizeof (int) == 4' and that you
>> have 8-bit bytes is to:
>>
>>     #define TT_ASSERT(message, test) \
>>       typedef char (message)[(test) ? 1 : -1]
>>
>>     TT_ASSERT(INT_IS_NOT_4_BYTES, sizeof (int) == 4);
>>     TT_ASSERT(NOT_8_BIT_BYTE, CHAR_BIT == 8);
>>
>>> Writing to one member of a union and reading from another member is
>>> implementation defined(K&    R).
>>
>> As far as I know, if 'sizeof (int) == 4' as shown, you can certainly
>> read from each element of the 'U.ch' array.  C doesn't guarantee that
>> 'sizeof (int) == 4', of course.
>>
>> Combined with the 'TT_ASSERT's above, you could have your union as:
>>
>>     union {
>>         unsigned int i;
>>         unsigned char ch[sizeof (unsigned int)];
>>       } U;
>>
>> (Note that the use of 'unsigned' attempts to avoid any potential sign
>> bit complications; the 'TT_ASSERT' might be better off matching, too.)
>>
>>> This example is used for testing
>>> endianess @ c-faq.com. I know that gcc allows this. Is the above
>>> snippet to test for endianess legal C or C++?
>>
>> If you know that the implementation definitely uses an 8-bit byte, a
>> 4-byte 'int', and that there are no padding bits and that '0x12345678'
>> is within the range of values for 'int', then I'd say yes for "legal C". :)
>
>> If you know that the implementation definitely uses an 8-bit byte, a
>> 4-byte 'int', and that there are no padding bits and that '0x12345678'
>> is within the range of values for 'int', then I'd say yes for "legal C". :)
>
> At least on my machine (Windows 7 64 bit) sizeof(int)==4,
> sizeof(char)==1 and '0x12345678' is within 'int' limit. But the fact
> is we are writing to int member and reading from (different) char
> member. That doesn't go well with union rules.

I believe it's quite all right.  6.5.2.3p3 has:

   "A postfix expression followed by the . operator and an identifier 
designates a member of a structure or union object. The value is that of 
the named member, and is an lvalue if the first expression is an lvalue. 
If the first expression has qualified type, the result has the 
so-qualified version of the type of the designated member."

Since you are using your 'ch' array, its element type is a character 
type, and there are no trap representations for character types.  The 
last-stored value for the union has an object representation[6.2.6.1p4] 
and that representation is then used for 'ch'.

Which union rules are you worried about, in particular?

> If it is legal in C
> language to reinterpret the content of any object as a char array (or
> char pointer), then I believe above snippet is technically correct C
> code(I may be wrong).

"char array": Yes.  "char pointer": I think you mean if it's accessed 
via a pointer to a character type.  Yes, that's quite often the case.

One of the guarantees of the character types is that all objects can 
have all of their bits manipulated/inspected via access through a 
character type.  This is useful for copying, for example.  Scalar types 
other than character types might have trap representations, if I recall 
correctly.

Another nice thing about character types is that they have the weakest 
alignment requirement; a pointer to a character type can be cast from 
any other pointer-to-object-type because the alignment is fine[6.3.2.3p7].

> Eg.
>     int i=0x12345678;    //  sizeof(int) == 4
>      char *p=(char *)&i;
>      if(*p==0x78)           // reinterpreting int i through a char
> pointer
>          puts("Little Endian");
>      else
>          puts("Big Endian");
>

Absolutely as legitimate as your previous code. :)

(Using 'unsigned' variants are "nicer," in my opinion; no sign bit.)

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


#6281

FromShao Miller <sha0.miller@gmail.com>
Date2011-06-17 13:33 -0500
Message-ID<itg36b$m9c$1@dont-email.me>
In reply to#6224
On 6/17/2011 7:57 AM, Stefan Ram wrote:
> Shao Miller<sha0.miller@gmail.com>  writes:
>> Which union rules are you worried about, in particular?
>
>    One might worry about not knowing whether or where C actually
>    specifies the value of a certain member. For example, in
>
>        U.i=0x12345678; // writing to int member
>        if ( U.ch[0]==0x78 )   // reading from char member
>
>    or
>
>        int i=0x12345678;    //  sizeof(int) == 4
>        char *ch=(char *)&i;
>
>    , we assume that the value *ch is a »window« into the
>    in-memory representation of i. but does the C standard
>    actually requires an implementation to behave this way
>    somewhere? If so, where?
>

6.2.6.1p4 defines "object representation."  The 'i' member and the union 
itself have an object representation.

6.2.6.1p5 allows for a an lvalue expression ('U.ch[0]') with a character 
type (such as 'char') to read the stored value.

6.5p7 confirms that an lvalue expression with a character type can read 
the stored value.

>> One of the guarantees of the character types is that all objects can
>> have all of their bits manipulated/inspected via access through a
>> character type.
>
>    Yes, it would be nice to know, where one can find this.
>    In the best case, all the steps needed to prove that *ch
>    really has the semantics as intended above.
>

Please see above, plus:

6.2.6p3 states that the representation of 'unsigned char' is "pure binary."

6.2.6.2p1 states that 'unsigned char' is not divided into value bits and 
padding bits.  Since it has values, that leaves only value bits.  That 
means that there is no bit which cannot be accessed.

The treatment of 'signed char' and implementations where 'char' is akin 
to 'signed char' simply has one of the bits being a sign bit[6.2.6.2p6].

Do you have alternative interpretations of these?

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


#6353

FromJames Kuyper <jameskuyper@verizon.net>
Date2011-06-18 09:18 -0400
Message-ID<iti8in$lje$1@dont-email.me>
In reply to#6281
On 06/18/2011 04:47 AM, Stefan Ram wrote:
> Shao Miller <sha0.miller@gmail.com> writes:
...
>>> U.i=0x12345678; // writing to int member
>>> if ( U.ch[0]==0x78 )   // reading from char
> 
>   And - while only �informative� - Annex J, J.1 �unspecified
>   behavior�, p1, states:
> 
>       �The following are unspecified: (...)
> 
>        -- The value of a union member other than the last one
>           stored into (6.2.6.1).�
> 
>   Above, �i� is the last union member stored into, so the value
>   of �ch� is unspecified. (Yes, that can be specifed by an
>   implementation, but we have not yet seen a quotation of such
>   an implementation specification here.)

Footnote 82: "If the member used to access the contents of a union
object is not the same as the member last used to
store a value in the object, the appropriate part of the object
representation of the value is reinterpreted
as an object representation in the new type as described in 6.2.6 (a
process sometimes called "type punning"). This might be a trap
representation."

Note: neither Annex J nor Footnote 82 are normative; what they say can
only be true if it can be derived from normative text. Both
cross-reference 6.2.6, but it's less than clear to me that either
statement is easily derived from anything it says in 6.2.6. I think that
the paragraph you quote from J.1p1 is out of date. I think that footnote
82 describes both the way real implementations have always worked, and
the committee's latest thinking on the subject.
-- 
James Kuyper

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


#6471

FromShao Miller <sha0.miller@gmail.com>
Date2011-06-19 17:22 -0500
Message-ID<itlsqg$j1t$1@dont-email.me>
In reply to#6281
On 6/18/2011 3:47 AM, Stefan Ram wrote:
> On 6/17/2011 1:33 PM, Shao Miller wrote:
>> On 6/17/2011 7:57 AM, Stefan Ram wrote:
>>> Shao Miller<sha0.miller@gmail.com> writes:
>>>> Which union rules are you worried about, in particular?
>>>
>>> One might worry about not knowing whether or where C actually
>>> specifies the value of a certain member. For example, in
>>>
>>> U.i=0x12345678; // writing to int member
>>> if ( U.ch[0]==0x78 ) // reading from char member
>>>
>>> or
>>>
>>> int i=0x12345678; // sizeof(int) == 4
>>> char *ch=(char *)&i;
>>>
>>> , we assume that the value *ch is a »window« into the
>>> in-memory representation of i. but does the C standard
>>> actually requires an implementation to behave this way
>>> somewhere? If so, where?
>>>
>>
>> 6.2.6.1p4 defines "object representation." The 'i' member and the union
>> itself have an object representation.
>>
>> 6.2.6.1p5 allows for a an lvalue expression ('U.ch[0]') with a character
>> type (such as 'char') to read the stored value.
>>
>> 6.5p7 confirms that an lvalue expression with a character type can read
>> the stored value.
>>
>>>> One of the guarantees of the character types is that all objects can
>>>> have all of their bits manipulated/inspected via access through a
>>>> character type.
>>>
>>> Yes, it would be nice to know, where one can find this.
>>> In the best case, all the steps needed to prove that *ch
>>> really has the semantics as intended above.
>>>
>>
>> Please see above, plus:
>>
>> 6.2.6p3 states that the representation of 'unsigned char' is "pure binary."
>>
>> 6.2.6.2p1 states that 'unsigned char' is not divided into value bits and
>> padding bits. Since it has values, that leaves only value bits. That
>> means that there is no bit which cannot be accessed.
>>
>> The treatment of 'signed char' and implementations where 'char' is akin
>> to 'signed char' simply has one of the bits being a sign bit[6.2.6.2p6].
>>
>> Do you have alternative interpretations of these?
>
>   What about ISO/IEC 9899:1999 (E) 6.7.2.1 p12?
>
>       »Each non-bit-field member of a structure or union
>       object is aligned in an implementation-defined manner
>       appropriate to its type.«
>
>   When this allows i and ch to have different alignments,
>   then the following might not behave as expected here.
>

#1: 'sizeof (char) == 1'[6.5.3.4p3].
#2: The size of a complete object type must be an integral multiple of 
the alignment requirement, else arrays would not be possible.
#1 && #2 --> #3: The alignment requirement for 'char' is '1'.
#4: The alignment requirement of an array is equal to the alignment 
requirement of the element type.
#3 && #4 --> #5: The alignment requirement of the 'U.ch' array is '1'.
#6: The alignment requirement of 'int' is X.
#7: There is no alignment requirement less than '1'.
#2 && #5 && #6 && #7 --> #8: The alignment requirement of 'U' is X.

Are you suggesting that members of a union might not have their 
lowest-addressed byte at the beginning of the union?  If so, please note 
6.5.8p5:

   "When two pointers are compared, the result depends on the relative 
locations in the address space of the objects pointed to. If two 
pointers to object or incomplete types both point to the same object, or 
both point one past the last element of the same array object, they 
compare equal. ... All pointers to members of the same union object 
compare equal. ..."

And 6.5.9p6:

   "Two pointers compare equal if and only if both are null pointers, 
both are pointers to the same object (including a pointer to an object 
and a subobject at its beginning) or function, both are..."

Also note the lack of any mention of such a license for padding before a 
member of a union (other than within the units in which bit-fields 
reside, which we aren't considering), but the mentions of padding in 
6.7.2.1p13:

   "... There may be unnamed padding within a structure object, but not 
at its beginning."

and in 6.7.2.1p15:

   "There may be unnamed padding at the end of a structure or union."

So are you suggesting that 6.7.2.1p12 is not a restriction on the 
alignment requirement of a union type (to satisfy each of its member 
types), but rather a license to have padding before a particular member?

>>> >>U.i=0x12345678; // writing to int member
>>> >>if ( U.ch[0]==0x78 )   // reading from char
>   And - while only »informative« - Annex J, J.1 »unspecified
>   behavior«, p1, states:
>
>       »The following are unspecified: (...)
>
>        -- The value of a union member other than the last one
>           stored into (6.2.6.1).«
>
>   Above, »i« is the last union member stored into, so the value
>   of »ch« is unspecified. (Yes, that can be specifed by an
>   implementation, but we have not yet seen a quotation of such
>   an implementation specification here.)
>

What are we discussing here, exactly?

The test function itself is attempting to test for one of two 
specifications, both of which include a 4-byte 'int' and (presumably) an 
8-bit byte: Little-endian, big-endian.

The values we will find in the elements of the 'ch' array are specified, 
in my opinion, insofar as they are the object representation of the 'i' 
member, because their sizes are the same and so they exactly overlap. 
In the case of 'char' being signed, one of the bits is a sign bit.

If we are questioning whether or not we can know the answer to the 
testing function from the C Standard: If we can, the testing function is 
redundant.  If we cannot, the testing function is fairly close to 
serving the intended purpose[*1], right?

[*1] It assumes 'sizeof (int) == 4' and assumes only two possibilities, 
allowing for false determinations if these criteria are not met.

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


#6477

FromTim Rentsch <txr@alumni.caltech.edu>
Date2011-06-19 16:24 -0700
Message-ID<kfntyblflq0.fsf@x-alumni2.alumni.caltech.edu>
In reply to#6281
ram@zedat.fu-berlin.de (Stefan Ram) writes:

> Shao Miller <sha0.miller@gmail.com> writes:
>>Do you have alternative interpretations of these?
>
>   What about ISO/IEC 9899:1999 (E) 6.7.2.1 p12?
>
>       >>Each non-bit-field member of a structure or union
>       object is aligned in an implementation-defined manner
>       appropriate to its type.<<
>
>   When this allows i and ch to have different alignments,
>   then the following might not behave as expected here.

Irrelevant since members in a union object must begin at the
same byte address.  How the union is aligned might change,
but where the members' objects are relative to each other cannot.


>>>U.i=0x12345678; // writing to int member
>>>if ( U.ch[0]==0x78 )   // reading from char
>
>   And - while only >>informative<< - Annex J, J.1 >>unspecified
>   behavior<<, p1, states:
>
>       >>The following are unspecified: (...)
>
>        -- The value of a union member other than the last one
>           stored into (6.2.6.1).<<
>
>   Above, >>i<< is the last union member stored into, so the value
>   of >>ch<< is unspecified. (Yes, that can be specifed by an
>   implementation, but we have not yet seen a quotation of such
>   an implementation specification here.)

If you read the referenced section (ie, 6.2.6.1), you will see
that this summary is an oversimplification.  Only those bytes
that don't correspond to the member being stored into take
unspecified values -- as must be true because the bytes that _do_
correspond to the member being stored into must take the byte
values representing the member's new value, and these bytes
coincide with those of other members, because the objects for
union members are defined to overlap.

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


Page 1 of 3  [1] 2 3  Next page →

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


csiph-web