2

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?

2 Answers2

3

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.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • Considering that *here* just one flag is required (ok maybe it is just an example), unsigned char without any bitfield logic would do. – Antti Haapala -- Слава Україні Sep 21 '18 at 07:30
  • 1
    "Non-deterministic" seems a bit strong. I would expect the behaviour of an individual compiler version for a specific platform - which is what you would normally document, yes? - to be consistent (for any compiler worthy of certification). Is this really that bad to document? – Alex Celeste Sep 21 '18 at 08:47
  • 1
    @Leushenko The alignment of a storage unit is not just implementation-defined, it is unspecified. Meaning that the same compiler is allowed to do it differently from time to time, and does not need to document when or how. So yes, bit-fields have non-deterministic behavior, from the programmer's point of view, as soon as they are used as something else than a chunk of boolean flags where allocation order or memory mapping doesn't matter. From the compiler's (internal) point of view, they are deterministic. – Lundin Sep 21 '18 at 08:52
1

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

Andrew
  • 2,046
  • 1
  • 24
  • 37
  • I wasn't aware of this part in that Appendix, so it seems part of my own answer is incorrect regarding essential type (will fix). However, what is a "signed type"? The C standard apparently doesn't specify if `int : n` is a bool, signed or unsigned type. And how is a static analyser supposed to know the implementation-defined behavior of the specific target? MISRA-C should just ban bit-fields entirely: they should never be allowed in critical systems. – Lundin Sep 24 '18 at 14:49
  • As a side-note, have you ever heard of any poor soul who has actually documented all implementation-defined aspects of bit-fields? As required by Directive 1.1. If MISRA insists on allowing bit-fields, perhaps they should also publish an application note/book containing all implementation-defined behavior of bit-fields, so that every single implementer of MISRA-C doesn't have to write such a book. – Lundin Sep 24 '18 at 14:57
  • Happy to take the suggestion to the team... of course, better would be for WG14 to fix it in the standard - but we know that will never happen :( – Andrew Sep 25 '18 at 19:20
  • 1
    Bit-fields is a notable hazard in embedded systems particularly, since one gets a bit-field-cluttered microcontroller register map with every tool chain nowadays. And indeed, if WG14 actually fixed the standard, MISRA-C wouldn't be needed :) – Lundin Sep 25 '18 at 20:26