avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-gcc-list] Bit-wise structure and unions


From: David Brown
Subject: Re: [avr-gcc-list] Bit-wise structure and unions
Date: Thu, 23 Nov 2006 08:42:21 +0100
User-agent: Thunderbird 1.5.0.8 (Windows/20061025)

David Gay wrote:
On 11/21/06, Eric Weddington <address@hidden> wrote:
Hi Keith

[Long time, no hear. ;-)]

Comments below.

> -----Original Message-----
> From:
> address@hidden
> [mailto:address@hidden
> org] On Behalf Of Keith Gudger
> Sent: Tuesday, November 21, 2006 11:41 AM
> To: address@hidden
> Subject: [avr-gcc-list] Bit-wise structure and unions
>
> Below is a program which illustrates the following issue:
>
<snip>

> But I would rather not have the union.  Is there any other way around
> this?  Thanks.
>

Unfortunately, no. The union would be the standard solution.

Ok, I take that back but only slightly. Why use bit fields at all? They are inherently non-portable between compilers (if they work, then you're lucky). Inherently, bit fields are tied to an int, which on the avr port is a 16-bit type. We're lucky in that you can get GCC to put them into an unsigned char.
But again, that's compiler dependent.

Actually a platform ABI for C normally specifies such things precisely
to avoid same-platform different-C-compiler portability problems
(there's way more things than just bitfields that are not specified by
the C standard, so such an ABI spec is a necessity). FWIW, avr-gcc
packs bitfields into bytes. The size of int or the type used to
declare the bitfield don't affect this packing (*). Whether this
matches what IAR C is doing is another question...


The ABI for a platform specifies a number of things, such as the size of datatypes and the calling conventions. Unfortunately, it does not specify bitfields very well - in particular, the ordering of the bits is not well defined, nor are any alignment requirements, and nor (IIRC) is the signedness of the bitfields. For example, consider the struct defined as:

        struct { unsigned char a : 1; int b : 2 };

It is not well defined whether the container for "a" takes the space of a whole int or just a byte, whether "b" is aligned to the next "int" alignment or is packed in with "a", and whether the whole structure takes a single byte, an int size, or two int sizes.

Secondly, it is not defined whether the bitfields are allocated from the LSB first or the MSB first. On most little-endian target-compiler combinations, it is LSB first, on big-endian target-compiler combinations, there is more variance (the m68k gcc port starts with the MSB). It is not even guaranteed to be consistent - MSVC++ famously changed the ordering between two versions of their compilers.

All in all, bitfields are strictly non-portable, not even between different compilers for the same target or different targets for the same compiler.

Having said that, two of the main uses for bitfields are for internal software structures such as packed flags (saving space), where alignment and ordering is of little concern, and for matching to hardware, where portability is of little concern. I find them convenient sometimes, and gcc handles them well, but make sure you check the assembly to find out exactly how your compiler handles its bitfields.


David Gay
*: If you're curious, avr-gcc doesn't define the magic
PCC_BITFIELD_TYPE_MATTERS flag in its configuration.






reply via email to

[Prev in Thread] Current Thread [Next in Thread]