简体   繁体   中英

How is the size of structures with bit-fields are calculated which contains some unnamed members and zero sized bit-fields?

How the size of this struct is calculated:

struct B {
    unsigned char c1 : 1;
    unsigned char : 2;
    unsigned char c2 : 2;
    unsigned char : 0;
    unsigned char c3 : 4;
    unsigned char c4 : 1;
};

What does this 0 stands for here?, does that mean that it is occupying 0-bits (ie no memory)

Can someone explain this to me that how its size is being calculated?

A bit-field of size 0 is used to specify that any following bit-fields are to be placed in a separate byte / unit. So the layout of the struct would probably look like this:

| c1|       |   c2  |           |      c3       | c4|           |
-----------------------------------------------------------------
|  0|  1|  2|  3|  4|  5|  6|  7|  8|  9| 10| 11| 12| 13| 14| 15|
-----------------------------------------------------------------

Without the field of size 0, it would probably look like this:

| c1|       |   c2  |      c3       | c4|                       |
-----------------------------------------------------------------
|  0|  1|  2|  3|  4|  5|  6|  7|  8|  9| 10| 11| 12| 13| 14| 15|
-----------------------------------------------------------------

Note however that the ordering of bit-fields in a struct is implementation defined, so it might not look exactly like this.

A bit-field length of 0 means start a new storage unit .

One possible layout for the structure in the question is:

  • an initial storage unit for member c1 , an unnamed member of length 2 and member c2 ,
  • a separate storage unit for members c3 and c4 .

Both of these storage units can be as small as a single byte as each contains only 5 bits of information, making struct B a 2-byte object, ie: sizeof(struct B) == 2 . But other sizes are possible, as the choice of storage unit is implementation defined and extra padding between members and at the end of the structure is also possible. Any size greater than 2 is possible. It is arguable that a size of 1 is not possible even on architectures where a byte can store at least 10 bits, because 2 storage units are required by the unsigned char: 0; member specification.

Here are the definitions from the C Standard:

6.7.2.1 Structure and union specifiers

Contraints
[...]
4 The expression that specifies the width of a bit-field shall be an integer constant expression with a nonnegative value that does not exceed the width of an object of the type that would be specified were the colon and expression omitted. If the value is zero, the declaration shall have no declarator.

5 A bit-field shall have a type that is a qualified or unqualified version of _Bool , signed int , unsigned int , or some other implementation-defined type. It is implementation-defined whether atomic types are permitted.

Semantics
[...]
9 A member of a structure or union may have any complete 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.

10 A bit-field is interpreted as having a signed or unsigned integer type consisting of the specified number of bits. If the value 0 or 1 is stored into a nonzero-width bit-field of type _Bool , the value of the bit-field shall compare equal to the value stored; a _Bool bit-field has the semantics of a _Bool .

11 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.

12 A bit-field declaration with no declarator, but only a colon and a width, indicates an unnamed bit-field. As a special case, a bit-field structure member with a width of 0 indicates that no further bit-field is to be packed into the unit in which the previous bit-field, if any, was placed.

Hence it is implementation defined how c1 and c2 are placed within their common storage unit, and the same goes for c3 and c4 . 10 implies that the choice of allocation unit be implementation defined, therefore the size of struct B is also implementation defined: it could be 2 , 4 , 8 , etc. As a matter of fact, the storage units do not need to have the same size and padding is permitted so any size greater than 1 is possible in theory.

The lack of a more precise and portable specification for bit-fields is quite counter-productive as these would be well tailored to map physical hardware devices. Differences in implementations in early C compilers and practical constraints related to endianness constraints prompted this flexibility in the specification and implementation variations especially regarding signed bit-fields made programmers reluctant to use this feature.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM