MergeMaster
MergeMaster

Reputation: 81

Safe assign of values to bitfield in C

Suppose I have

typedef struct {
    unsigned short bar   :    1;
} foo_bf;

typedef union {
  unsigned short val;
  foo_bf bf;
} foo_t;

How do I correctly assign a value to this bitfield from an type e.g uint16_t?

uint16_t myValue = 1;
foo_t foo;
foo.bf.bar = myValue 

Running PC-Lint, this turns into a MISRA error: Expression assigned to a narrower or different essential type.

I tried to limit the number of used bits without any success.

foo.bf.bar = (myValue 0x1U)

Is there any chance to get it MISRA complient if I have to use a uint16_t value as origin?

Upvotes: 2

Views: 1547

Answers (2)

Lundin
Lundin

Reputation: 214780

MISRA-C's essential type model isn't really applicable to bit-fields. The terms narrower and wider refer to the size in bytes (see 8.10.2). So it isn't obvious if a static analyser should warn here or not, since the rules for essential type do not address bit-fields.
EDIT: I was wrong here, see the answer by Andrew. Appendix D.4 tells how to translate a bit-field type to the matching essential type category.

However, using bit-fields in a MISRA-C application is a bad idea. Bit-fields are very poorly specified by the standard, and therefore non-deterministic and unreliable. Also, MISRA-C 6.1 requires that you document how your compiler supports bit-fields with uint16_t, as that is not one of the standard integer types allowed for bit-fields.

But the real deal-breaker here is Directive 1.1, which requires that all implementation-defined behavior is documented and understood. For a MISRA-C implementation, I once actually tried to document all implementation-defined aspects of bit-fields. Soon I found myself writing a whole essay, because there are so many problems with them. See this for the top of the iceberg.

The work-around for not having to write such a "bit-field behavior book" is to unconditionally ban the use of bit-fields entirely in your coding standard. They are a 100% superfluous feature anyway. Use bit-wise operators instead.

Upvotes: 3

Andrew
Andrew

Reputation: 2322

Appendix D.4 of MISRA C:2012 is usefully titled "The essential types of bit fields"

  • For a bit-field which is implemented with an essentially Boolean type, it is essentially Boolean
  • For a bit-field which is implemented with a signed type, it is the Signed Type of Lowest Rank which is able to represent the bit field
  • For a bit-field which is implemented with a unsigned type, it is the Unsigned Type of Lowest Rank which is able to represent the bit field

The Unsigned Type of Lowest Rank of a single-bit unsigned integer would be uint8_t (aka unsigned char) - assuming that the tool does not interpret a single-bit as being boolean...

Beyond observing that this looks like a mis-diagnosis by PC-Lint, a workaround that avoids any possibility of doubt would to cast:

foo.bf.bar = (uint8_t)myValue

As an aside MISRA C:2012 Rule 6.1 gives guidance on the use of types other than signed/unsigned int for bit-fields...

Upvotes: 1

Related Questions