ProgrammingEmbedded C Developer

Explain the specifics of working with bit fields in C structures. How to properly declare them, where to apply them, what limitations and pitfalls exist?

Pass interviews with Hintsage AI assistant

Answer

Bit fields in C are members of a structure that occupy a specified number of bits instead of the standard size of the type. They help save memory, especially for storing flags and compact sets of states.

Declaration:

struct Flags { unsigned int enable : 1; unsigned int mode : 2; unsigned int code : 5; };

In this example, the structure occupies a minimum of 8 bits, rather than 3 * sizeof(unsigned int).

Where to apply:

  • Protocols where space saving is important (e.g., fitting into hardware registers)
  • Storing compressed data, flags, states

Limitations and pitfalls:

  • Strict dependence of layout on the specifics of the compiler and CPU architecture (offset and alignment are not standardized)
  • Cannot take the address of a bit field
  • Cannot directly create arrays of bit fields
  • Read/write operations are often converted to the container type, which affects portability

Example:

struct Packet { unsigned char start : 1; unsigned char id : 3; unsigned char flag : 4; };

Trick Question

Question: Can you use char or signed int types for bit fields?

Answer: The C standard allows using int, unsigned int, and (according to compiler extensions) other standard integer types (char, short). However, portability is guaranteed only for int and unsigned int.

Example of error:

struct Example { signed char a : 3; }; // Different compilers/architectures may have different rules for sign storage and bit order.

Examples of real errors due to lack of knowledge of the nuances of the topic


Story

When integrating software on ARM and x86, it became clear that a structure with bit fields unpacked differently: various bit order and alignment. The design did not account for these differences, leading to an inability to read data in a cross-platform environment.


Story

In the motor controller management system, the char type was mistakenly used in bit field structures. On some ARM processors, this resulted in incorrect sign extension, leading to erroneous flag processing.


Story

In a network protocol, bit fields were used to pack message flags; it was not noted that higher uninitialized fields remain junk. When transmitting between devices, random state errors occurred due to differences in initialization.