This may be a FAQ, in which case you all may (probably will) yell at
me.
I haven't coded in plain C for almost 20 years, so I hope the following
code is actually done right.
Suppose the following declaration:
union {
unsigned int uvalue;
unsigned nybbles:4[8];
unsigned bits:1[32];
struct {
unsigned nybble0:4;
unsigned nybble1:4;
unsigned nybble2:4;
unsigned nybble3:4;
unsigned nybble4:4;
unsigned nybble5:4;
unsigned nybble6:4;
unsigned nybble7:4;
} nybblepack;
struct {
unsigned bit0:1;
unsigned bit1:1;
unsigned bit2:1;
unsigned bit3:1;
unsigned bit4:1;
unsigned bit5:1;
unsigned bit6:1;
unsigned bit7:1;
// ...
} bitpack;
} testorder;
and the following code
testorder.uvalue = 0x12345678;
for ( i=0; i<8 ) printf("nybbles[%i] = %i", i, testorder.nybbles[i]);
for ( i=0; i<32 ) printf("bits[%i] = %i", i, testorder.bits[i]);
printf("nybble0 = %i", testorder.nybblepack.nybble0);
printf("nybble1 = %i", testorder.nybblepack.nybble1);
printf("nybble2 = %i", testorder.nybblepack.nybble2);
printf("nybble3 = %i", testorder.nybblepack.nybble3);
printf("nybble4 = %i", testorder.nybblepack.nybble4);
printf("nybble5 = %i", testorder.nybblepack.nybble5);
printf("nybble6 = %i", testorder.nybblepack.nybble6);
printf("nybble7 = %i", testorder.nybblepack.nybble7);
printf("bit0 = %i", testorder.bitpack.bit0);
printf("bit1 = %i", testorder.bitpack.bit1);
printf("bit2 = %i", testorder.bitpack.bit2);
printf("bit3 = %i", testorder.bitpack.bit3);
printf("bit4 = %i", testorder.bitpack.bit4);
printf("bit5 = %i", testorder.bitpack.bit5);
printf("bit6 = %i", testorder.bitpack.bit6);
printf("bit7 = %i", testorder.bitpack.bit7);
//...
Assuming a standards compliant compiler, would it produce the same
output on all machines? (I suspect not, if for no other reason than
that an int may be larger than what's necessary to store 2^32-1.)
Would it produce the same output on the same machine with different
compliant compilers?
Can anyone refer me to the relevant section in the standard?
--
Helge Moulding
mailto:hmoulding@gmail.com Just another guy
http://hmoulding.cjb.net/ with a weird name
|
|
0
|
|
|
|
Reply
|
hmoulding1 (10)
|
2/11/2005 8:54:21 PM |
|
hmoulding@gmail.com wrote:
> This may be a FAQ, in which case you all may (probably will) yell at
> me.
> I haven't coded in plain C for almost 20 years, so I hope the following
> code is actually done right.
>
> Suppose the following declaration:
>
> union {
> unsigned int uvalue;
> unsigned nybbles:4[8];
> unsigned bits:1[32];
Bzzt! The compiler rejects this line, because you
can't make arrays of bit-fields. (... because you can't
make a pointer to a bit-field, and C array indexing is
defined in terms of pointer arithmetic.) Let's just
pretend this line and the related loop below are deleted.
> struct {
> unsigned nybble0:4;
> unsigned nybble1:4;
> unsigned nybble2:4;
> unsigned nybble3:4;
> unsigned nybble4:4;
> unsigned nybble5:4;
> unsigned nybble6:4;
> unsigned nybble7:4;
> } nybblepack;
> struct {
> unsigned bit0:1;
> unsigned bit1:1;
> unsigned bit2:1;
> unsigned bit3:1;
> unsigned bit4:1;
> unsigned bit5:1;
> unsigned bit6:1;
> unsigned bit7:1;
> // ...
> } bitpack;
> } testorder;
>
> and the following code
>
> testorder.uvalue = 0x12345678;
> for ( i=0; i<8 ) printf("nybbles[%i] = %i", i, testorder.nybbles[i]);
> for ( i=0; i<32 ) printf("bits[%i] = %i", i, testorder.bits[i]);
We're pretending this line is deleted, right?
> printf("nybble0 = %i", testorder.nybblepack.nybble0);
> printf("nybble1 = %i", testorder.nybblepack.nybble1);
> printf("nybble2 = %i", testorder.nybblepack.nybble2);
> printf("nybble3 = %i", testorder.nybblepack.nybble3);
> printf("nybble4 = %i", testorder.nybblepack.nybble4);
> printf("nybble5 = %i", testorder.nybblepack.nybble5);
> printf("nybble6 = %i", testorder.nybblepack.nybble6);
> printf("nybble7 = %i", testorder.nybblepack.nybble7);
> printf("bit0 = %i", testorder.bitpack.bit0);
> printf("bit1 = %i", testorder.bitpack.bit1);
> printf("bit2 = %i", testorder.bitpack.bit2);
> printf("bit3 = %i", testorder.bitpack.bit3);
> printf("bit4 = %i", testorder.bitpack.bit4);
> printf("bit5 = %i", testorder.bitpack.bit5);
> printf("bit6 = %i", testorder.bitpack.bit6);
> printf("bit7 = %i", testorder.bitpack.bit7);
> //...
>
> Assuming a standards compliant compiler, would it produce the same
> output on all machines? (I suspect not, if for no other reason than
> that an int may be larger than what's necessary to store 2^32-1.)
Or smaller, for that matter. And, no: You will not
necessarily get the same output on all implementations.
In theory, at least, you might not get any output at all:
storing into one member of a union and then reading from
a different member produces undefined behavior.
Even if "all goes well" you won't always get the same
output. There are "endianness" issues, there's the question
of how the compiler decides to arrange the bit-fields (it
has quite a lot of freedom), there's possible padding within
the structs that are members ...
> Would it produce the same output on the same machine with different
> compliant compilers?
The Standard speaks only of "the implementation," and
doesn't divide it into separate components. We may think of
the compiler, the library, the O/S, and the hardware as distinct
pieces of the implementation, but as far as the Standard is
concerned changing any of these pieces gives a different
"implementation" altogether. The Standard does not require
different implementations to agree on such details.
> Can anyone refer me to the relevant section in the standard?
You've asked about things that are spread fairly widely
through the Standard, so this list is incomplete:
6.2.5 Types
6.2.6 Representations of types
6.7.2.1 Structure and union specifiers
--
Eric.Sosman@sun.com
|
|
0
|
|
|
|
Reply
|
Eric.Sosman (4228)
|
2/11/2005 9:30:27 PM
|
|
hmoulding@gmail.com wrote in news:1108155261.220594.188100
@o13g2000cwo.googlegroups.com:
Emmmm.. bit fields are pretty much machine-dependent..
Frem "C: A Reference Manual" Samuel Harbison/Guy Steele:
"Bit fields are typically used in machine-dependent programs that
must force a data structure to correspond to a fixed hardware
representation.."
Now, your printf() output would probably look the same across
different plaforms, but if you were to create a binary file on one
machine using a bitfield structure, it might not be read back the
same way on a different machine platform.
> This may be a FAQ, in which case you all may (probably will) yell at
> me.
> I haven't coded in plain C for almost 20 years, so I hope the following
> code is actually done right.
>
> Suppose the following declaration:
>
>
> Assuming a standards compliant compiler, would it produce the same
> output on all machines? (I suspect not, if for no other reason than
> that an int may be larger than what's necessary to store 2^32-1.)
>
> Would it produce the same output on the same machine with different
> compliant compilers?
>
> Can anyone refer me to the relevant section in the standard?
> --
> Helge Moulding
> mailto:hmoulding@gmail.com Just another guy
> http://hmoulding.cjb.net/ with a weird name
>
>
|
|
0
|
|
|
|
Reply
|
georgewicks (17)
|
2/11/2005 9:35:28 PM
|
|
Eric Sosman wrote:
> hmoulding@gmail.com wrote:
> > unsigned bits:1[32];
> Bzzt! The compiler rejects this line, because you
> can't make arrays of bit-fields. (... because you can't
> make a pointer to a bit-field, and C array indexing is
> defined in terms of pointer arithmetic.)
I knew that. I mean, I knew that the standard doesn't define
pointers to bit fields (I think implementations may have them),
but I didn't think through the necessary implications for
arrays.
> And, no: You will not necessarily get the same output on all
> implementations.
OK, that's what I thought I remembered. Each implementation
has to have its own hardware specific stuff if you want to
mess around at the hardware level.
> In theory, at least, you might not get any output at all:
> storing into one member of a union and then reading from
> a different member produces undefined behavior.
I suppose that makes sense, but it's difficult in that case
to explain the use of unions in the first place, isn't it?
> You've asked about things that are spread fairly widely
> through the Standard, so this list is incomplete:
> 6.2.5 Types
> 6.2.6 Representations of types
> 6.7.2.1 Structure and union specifiers
All the same, this is more than I was able to figure out
after poking around with Google for an hour. Thanks a bunch!
--
Helge Moulding
mailto:hmoulding@gmail.com Just another guy
http://hmoulding.cjb.net/ with a weird name
|
|
0
|
|
|
|
Reply
|
hmoulding1 (10)
|
2/11/2005 9:58:17 PM
|
|
Helge Moulding wrote:
> Eric Sosman wrote:
>
>>In theory, at least, you might not get any output at all:
>>storing into one member of a union and then reading from
>>a different member produces undefined behavior.
>
> I suppose that makes sense, but it's difficult in that case
> to explain the use of unions in the first place, isn't it?
Unions are mostly space-savers, like "variant records"
in Pascal:
struct shape {
enum { RECTANGLE, SQUARE, ELLIPSE, CIRCLE } type;
union {
struct { double wide, tall; } rectangle;
struct { double side; } square;
struct { double major, minor; } ellipse;
struct { double radius; } circle;
} data;
};
If you really want to peek and poke at the representations
of data objects (C programmers seem to indulge in this far
more often than they actually need to), the sanctioned way
is to use an `unsigned char*' to inspect/adjust the bytes
individually:
/* How is an `unsigned int' arranged? */
unsigned int data = 0x12345678;
unsigned char *p = (unsigned char*) &data;
printf ("0x%08X =>", data);
while (p < (unsigned char*)(&data + 1))
printf (" %02X", (unsigned int)*p++);
printf ("\n");
(There are some non-portable assumptions built into this
code, but if they're wrong you'll just get ugly output, not
anything "really bad.")
--
Eric.Sosman@sun.com
|
|
0
|
|
|
|
Reply
|
Eric.Sosman (4228)
|
2/11/2005 10:57:55 PM
|
|
The following article about bye alignment and ordering should help:
http://www.eventhelix.com/RealtimeMantra/ByteAlignmentAndOrdering.htm
Deepa
--
EventStudio 2.5 - http://www.EventHelix.com/EventStudio
Enter model in plain text;generate sequence diagram in PDF/Word
|
|
0
|
|
|
|
Reply
|
eventhelix (355)
|
2/12/2005 11:41:56 AM
|
|
On 12 Feb 2005 03:41:56 -0800, EventHelix.com
<eventhelix@gmail.com> wrote:
> The following article about bye alignment and ordering should help:
>
> http://www.eventhelix.com/RealtimeMantra/ByteAlignmentAndOrdering.htm
It's a good illustration. It does however miss one thing -- apart from
char, the integer types in C aren't specified as to size (except that
short is at least as big as char, int is at least as big as short, and
long is at least as big as int; and short and int are at least 16 bits
and long is at least 32 bits). So specifying a structure as:
struct packet
{
long ll;
short ss;
char cc;
};
is still not defined even if you know that the byte ordering and
alignment are correct, because on one machine long might be 32 bits and
on another 64 bits (or even 36, 40, 48 or even stranger sizes). For
that matter a char may be anything at least 8 bits (9, 12, 24...).
The only way to deal with structures portably is to convert them "by
hand". I usually have routines:
void pack_1_octet(unsigned char *buffer, unsigned char val);
void pack_2_octet(unsigned char *buffer, unsigned int val);
void pack_4_octet(unsigned char *buffer, unsigned long val);
unsigned char unpack_1_octet(unsigned char *buffer);
unsigned int unpack_2_octet(unsigned char *buffer);
unsigned long unpack_4_octet(unsigned char *buffer);
or something like that, so that the byte order and size remains
constant whatever the compiler and target.
Chris C
|
|
0
|
|
|
|
Reply
|
chris23 (644)
|
2/12/2005 9:17:42 PM
|
|
|
6 Replies
22 Views
(page loaded in 0.137 seconds)
Similiar Articles: MMX reverse byte order instr. - comp.lang.asm.x86... that there is MMX instruction that reverses byte order in MMX ... Signed shift of 32-bit int using 16-bit instructions? - comp.lang ... MMX reverse byte order instr. - comp ... Reversing bit order in delphi ? - comp.lang.asm.x86The byte order and bit order of data in RAM is both Little Endian for intel. (LSB) The byte order and bit order of CPU registers is both Little Endian for intel. accept() and getpeername() return 0.0.0.0 - comp.sys.hp.hpux ...In 64-bit a long is 8 bytes and an int is 4 bytes (hence that warning - 64-bit HP-UX is ... of the things (I'm guessing) is such that the pointer is to the high-order bytes ... Compiler for 16bit architecture - comp.compilers.lcc> > You take it for granted that you can't address bits 1-4 of a byte as a > unit. > Because ... Like many other compilers, the ... in order to provide support for the ... How to port 32 bit unsigned char* to 64 bit - comp.lang.c++ ...In sum, your problems (as far as I can tell) have nothing to do with porting to 64 bits ... up through the late 1980's, and is still allowed by many compilers in order to ... Problem in porting from 32 bit to 64 bit application - comp.os.ms ...... szControlName); hWnd2=hwndstatic; if(hWnd2!=NULL) { //if Z order is ... Porting 32-Bit Code to 64-Bit Code Porting 32-Bit Code to 64-Bit Code ... This topic ... XML-Parsing with UTF-8 Byte-Order-Mark (BOM) - comp.lang.java ...UTF-16 Sixteen-bit UCS Transformation Format, byte order identified b= y an optional byte-order mark ... UTF-8 encoded. Same with XML. "\uxxxx" is a good suggestion, but ... ALIGN Question for MASM - comp.lang.asm.x86Why is it necessary to use ALIGN 4 for BYTE and WORD? If I have to use ALIGN ... agree, but I still have to add one extra cycle by adding ADC in order > to use 8 bit carry ... portability of integral types in C++ on UNIX - comp.unix ...... integral types available on my system, for portability ... define UNSIGNED 0 char * getMatchingType(int bytes ... sizeof(int) can > equal 1 yet still have 16 value bits ... Fast bit-reverse on an x86? - comp.dsp> > > > > > > As it is, the pseudo-code reorders the bytes but it leaves the > bit order inside the bytes intact. That's what the "move byte" were for, byte table lookup... Bit and Byte Order Portability - C / C++Bit and Byte Order Portability. C / C++ Forums on Bytes. Byte Addressing for Efficiency and PortabilityByte Addressing for Efficiency and Portability Because the Leptonica library is ... the relation between the byte order and ... by saying that for each 32-bit word, the bytes ... 7/23/2012 8:31:03 AM
|