How to assign bitfield variable to uint8_t variable without violating MISRA rules?

I have a typedef struct named Character.

typedef struct {
    unsigned int a : 1;
    unsigned int b : 1;
    unsigned int c : 1;
    unsigned int d : 1;
    unsigned int o : 1;
    unsigned int p : 1;
    unsigned int q : 1;
    unsigned int x : 1;
} Character;

static Character tempChar;

void writeVar(const uint8_t *pData)
{
    tempChar.a = pData[0] >> 5;
    ...
}

When I try to assign an uin8_t variable (with value 0 or 1) to one of these bitfields, I got a violation to MISRA rule 10.6 which states that:

The value of a composite expression shall not be assigned to an object with wider essential type

Is there a way to assign a bit-field to uint8_t without violating MISRA C?

Both operands in the expression pData[0] >> 5 will, if needed, be promoted to int (it will happen for pData[0]).

And the result of the expression is an int.

Both the promotion and the conversion from int to unsigned int, while perfectly valid and fine in normal cases, is enough for the very strict MISRA to complain.

Simple solution (as shown in comments) is to explicitly convert pData[0] to unsigned int using casting.

Bitfields � Stack Overflow, A flags variable is nothing more than an integral type that I wish to treat as an When I'm running short on RAM and thus assigning an entire byte or integer to I have used a union of an integral type (uint8_t) and a structure of bitfields. to standard C (which violates the MISRA requirement for no use of� The variables defined with a predefined width are called bit fields. A bit field can hold more than a single bit; for example, if you need a variable to store a value from 0 to 7, then you can define a bit field with a width of 3 bits as follows − struct { unsigned int age : 3; } Age;

I find MISRA C over-complicated for this very reason. Anyways, You didn't say you want to assign it directly. If that is the case, you can resort to the following:

typedef union {

    struct {
        unsigned int a : 1;
        unsigned int b : 1;
        unsigned int c : 1;
        unsigned int d : 1;
        unsigned int o : 1;
        unsigned int p : 1;
        unsigned int q : 1;
        unsigned int x : 1;
    };

    uint8_t u8Value;

} Character;

And setting those values by accessing tempChar.u8Value instead of the bit fields. For example,

tempChar.Value |= (1 << 0);

would set tempChar.a to 1.

That would still keep the neatness (readability) of code to the same extent. For example,

if(1 == tempChar.a)
{ 
    // Some code
}

INT02-C. Understand integer conversion rules, Conversion of an operand value to a compatible type causes no change to the Integer promotions require the promotion of each variable ( c1 and c2 ) to int size. occur when narrowing the type (which requires a specific cast or assignment), Search for vulnerabilities resulting from the violation of this rule on the CERT� :shock: Egad! Yeah, that will work. You have to admit, though, that it's a bit byzantine. I have to commiserate with newbies sometimes. After all, this isn't a terribly hard concept.

tempChar.a = pData[0] >> 5;

In this 5 is a signed integer constant. You should use 5U for an unsigned constant

Also, the result of the right shift operation will be an int So you need to type cast the result back to unsigned int

tempChar.a = (unsigned int) (pData[0] >> 5U);

EXP14-C. Beware of integer promotion when , INT02-C. Understand integer conversion rules. Integer types uint8_t. 0x5a. ~ port. int. 0xffffffa5. ~port >> 4. int. 0x0ffffffa. Whether or not value is negative is� Variables in MATLAB of data type (class) uint8 are stored as 1-byte (8-bit) unsigned integers.

The core problem here has nothing to do with MISRA, but with attempting to store a value at a specific slot in a bit-field. You cannot know how your bit-field layout actually ends up in memory, because that's not defined in the C standard.

Is your bit-field allocating 8 value bits in the MS byte or LS byte? Is it taking endianess in accordance or is it not? What is the bit order? Nobody knows. Step 1 is to get rid of the bit-field.

Step 2 is to get rid of anything unsigned int and use uint16_t/uint32_t.


As for MISRA-C 10.6 specifically, the rule against implicit conversion to a wider type was always rather misguided. The rationale MISRA used for this rule was to prevent people from writing code like uint32_t u32 = u16a + u16b; and thinking that the u32 operand of = somehow magically means that the operation will get carried out on 32 bits instead of 16. But on a 8/16 bit system, it is carried out with 16 bit arithmetic and there might be overflows/wrap-around.

Now as it happens, doing bit-shifts on signed types is always a very bad idea. pData[0] gets implicitly promoted to int which is signed. There are other MISRA rules dealing with this, rather than the one you quoted.

Regardless of MISRA, you should make a habit of always carrying out your shifts on unsigned types. "It's not dangerous in this case" is a bleak rationale. That means always write (uint32_t)pData[0] >> 5 and the cast should be applied before the shift not after it. This removes all uncertainties regarding undefined behavior left shifts and potentially arithmetic right shifts etc. Let the optimizer worry about the actual used size of the operands from there.

MISRA C:2004 and MISRA AC AGC Coding Rules, However, the software detects violations of rules 9.1 ( Non-initialized variable ) Standard compilation error messages do not lead to a violation of this MISRA rule and No warning on anonymous signed int bitfields of width 0 - Extended to all All automatic variables shall have been assigned a value before being used. Bitfield operations. Bitfields are ranges of bits inside a variable that act as as a sub-variable. The basic operations here are set and get. For both of these, you need to careful not to disturb the other bits in the same variable (masking) and to shift left/right to align the value with the bitfield.

[PDF] MISRA-C:2004 - Guidelines for the use of the C language in , We have replaced “as appropriate” rules with definitive do / do not rules. The “ bit field” facility in C is one of the most poorly typedef unsigned char uint8_t; /* Not compliant - redefinition */ included in multiple source files, this rule is not violated. All automatic variables shall have been assigned a value before. The remaining examples involving bit-field rules. These are being accessed through a pointer to unsigned char, which is actual an exclusion of EXP39-C. Do not access a variable through a pointer of an incompatible type .

[PDF] Guidelines for the use of the C++14 language in critical , adopted from MISRA C++ without modifications, are only referred in this The rule set for security (as long as it is not common to critical software or safety- constexpr std::uint8_t limit{100U};. 66 of a captured variable does not violate the rule. When the absolute positioning of bits representing a bit-field is required,. The software reports most violations during the compile phase of an analysis. However, the software detects violations of rules 9.1 (Non-initialized variable), 12.11 (one of the overflow checks) using -scalar-overflows-checks signed-and-unsigned), 13.7 (dead code), 14.1 (dead code), 16.2 and 21.1 during code analysis, and reports these violations as run-time errors.

[PDF] Embedded System development Coding Reference guide, Lastly but not least, we would like to thank the members of Coding Practices Guide The appropriate methods to deal with rule violations MISRA C refers collectively to the coding guidelines for C language defined by The Motor Industry in the variable declaration where the initial value is specified. Bad Rule #2: Use variable types in relation to the maximum value that variable may take. BadAdvice gives the example of a variable named seconds, which holds integer values from 0 to 59. And he shows choosing char for the type over int. His stated goal is to reduce memory use.

Comments
  • How do you got this warning? How do you compile the code?
  • I'm using a tool to do the static analysis. I have to comply with MISRA C.
  • Have you tried tempChar.a = (uint8_t)(pData[0] >> 5); ?
  • Yes I did. It didn't help.
  • Try avoiding int promotion: tempChar.a = ((unsigned)pData[0]) >> 5;
  • Oh, simpler. Why did I think of union in the first place! :(
  • Run the same code with ~pData[0] >> 5. And then after that, ~(uint32_t)pData[0] >> 5. Then complain about MISRA... unless of course you believe storing the value -1 in a :1 bit-field is a good idea.