MISRA Discussion Forums

Full Version: Packed struct
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
is packing of structures allowed within Misra C?

I only wish to use the structure to overlay a generic byte array, which is populated from an external interface serialy. However the structure has 7 bytes but without packing has 8.

What i want is to be able to index into the generic array as such

sCFG *ptr = &genericArray[0];

for(i=0u; i< 10u; i++){
ptr[i].CFG0 = 10u;

But because without packing the struct is 1 byte larger, i will end up misaligned.
So basically can i pack my structure to acheive this goal?

Thank you


typedef struct{
u8 CFG0;
u8 CFG1;
u8 CFG2;
u8 CFG3;
u8 CFG4;
u8 CFG5;
u8 CFG6;
}sCFG ;
An implementation is free to choose its own layout for structures provided that the offsets of the addressable members increase in the order that the members appear in the declaration. Provided that the packing does not alter the order of the addressable members then it does not constitute a language extension itself although the methods by which it is controlled may do so.

In some implementations, structures may be packed with little or no performance penalty. However, some processors take longer to perform misaligned memory accesses and some may even have to take a memory fault exception in order to emulate the access, resulting in a significant performance penalty. Given that the accesses in the example are all single-byte accesses, it is unlikely that there will be a performance problem in this case.

It is clearly important that all all declarations of a given structure are processed with the same packing options. If packing is controlled by means of command-line options or IDE settings then these will need to be the same for all translation units. If packing is controlled by means of pragmas then all declarations of a given structure will need to have the same pragmas in force, e.g. by placing the pragma(s) and declaration in a header file. If packing is controlled by means of new keywords then this will be a language extension and will require a deviation of Rule 1.1.

Regardless of how packing is controlled, it is important to ensure that it is documented sufficiently well for your purposes. It would also be prudent to ensure that the packing really does achieve the desired effect, for example by means of an automated build-time check, a run-time check (e.g. at initialisation) or a review of the compiler output.

Note that casting from a pointer to object into a pointer to a different object breaks Advisory Rule 11.4 and that using a pointer as an array breaks Required Rule 17.4.

If the code were written as:
for (i = 0u; i < 10u; i++) {
  sCFG *ptr = (sCFG *)&genericArray[7 * i];
  ptr->CFG0 = 10u;
then it would comply with Rule 17.4. However, it would still need a deviation against Rule 11.4 and would still depend on ensuring that sCFG is packed to 7 bytes.

Depending on your design, another more portable option might be to code the member accesses in longhand, perhaps wrapped as a macro, although this may require more and / or slower code, e.g.
#define CFG0(N) (genericArray[(7 * (N)) + 0])
#define CFG1(N) (genericArray[(7 * (N)) + 1])

for (i = 0u; i < 10u; i++){
  CFG0(i) = 10u;