Can someone explain the following syntex. What does it mean and
why does it have to be inside a struct and not as an stand alone
unsigned int/char.
It is tempting to ask "what does your book-on-C say", but a lot
of books-on-C are not so good.
struct {
unsigned char a:1;
[snippage]
This is a struct (with no tag, in this case) followed by a
"struct-declarator-list", and as such, it declares a new type.
In general, one should usually include a tag, e.g.:
struct zorg {
because without a tag, there is no way to refer back to the
same struct-type later. (There are specific exceptions to
this rule, but "in general" it is best to use tags.)
Presumably, however, the syntax you are interested in is the
part that happens after the open-brace, i.e., the
unsigned char a:1;
part. Here we need to look at the grammar specified in the
C Standard, which reads in part:
struct-declaration-list:
struct-declaration
struct-declaration-list struct-declaration
struct-declaration:
specifier-qualifier-list struct-declarator-list ;
specifier-qualifier-list:
type-specifier specifier-qualifier-list-opt
type-qualifier specifier-qualifier-list-opt
struct-declarator-list:
struct-declarator
struct-declarator-list , struct-declarator
struct-declarator:
declarator
declarator-opt : constant-expression
In this case, the grammar production involved is the very last one
-- an optional declarator, followed by a colon (':') character,
followed by an integral constant expression. In this case, the
declarator -- "unsigned char a" -- is present. The Standard then
goes on to say:
[#7] A member of a structure or union may have any object
type other than a variably modified type. In addition, a
member may be declared to consist of a specified number of
bits (including a sign bit, if any). Such a member is
called a bit-field; its width is preceded by a colon.
[#8] A bit-field shall have a type that is a qualified or
unqualified version of signed int or unsigned int. A bit-
field is interpreted as a signed or unsigned integer type
consisting of the specified number of bits.
Thus, this structure-member (the one named "a") is a "bit-field",
consisting of one (1) bit. The type -- "unsigned char" -- is
incorrect and invalid; a diagnostic is required.
Finally:
[#9] An implementation may allocate any addressable storage
unit large enough to hold a bit-field. If enough space
remains, a bit-field that immediately follows another bit-
field in a structure shall be packed into adjacent bits of
the same unit. If insufficient space remains, whether a
bit-field that does not fit is put into the next unit or
overlaps adjacent units is implementation-defined. The
order of allocation of bit-fields within a unit (high-order
to low-order or low-order to high-order) is implementation-
defined. The alignment of the addressable storage unit is
unspecified.
Hence, exactly which bit the member "a" represents, within whatever
"unit of storage" the implementation chooses to use, is up to the
implementation. Or, in less general but perhaps more understandable
terms, you -- the C programmer -- have said: "Hey, Mister Compiler,
pick out some glob of bytes somewhere, and then pick out one bit
within that glob of bytes, and use that bit, but don't tell me
which bit in which bytes, because I don't care!"
If you *do* care which bit(s) are used in which byte(s), do not
use bitfields.