Question

I've read this about structure padding in C: http://bytes.com/topic/c/answers/543879-what-structure-padding and wrote this code after the article, what should print out size of 'struct pad' like 16 byte and the size of 'struct pad2' should be 12. -as I think. I compiled this code with gcc, with different levels of optimization, even the sizeof() operator gives me both of them 16 byte. Why is it?

This information is necessary for me because of PS3 machines, where the byte boundaries and exploitation of the full dma transfer is important:

#include <stdio.h>
#include <stdlib.h>

struct pad
{
    char  c1;  // 1 byte
    short s1;  // 2 byte
    short s2;  // 2 byte
    char  c2;  // 1 byte
    long  l1;  // 4 byte
    char  c3;  // 1 byte
};

struct pad2
{
    long  l1;
    short s1;
    short s2;
    char  c1;
    char  c2;
    char  c3;
};

int main(void)
{
    struct pad P1;
    printf("%d\n", sizeof(P1));

    struct pad P2;
    printf("%d\n", sizeof(P2));

    return EXIT_SUCCESS;
}
Was it helpful?

Solution

There are two tricks that can be used to owercome this problem

  1. Using directive #pragma pack(1) and then #pragma pack(pop) example:

    #pragma pack(1)
    
    struct tight{           
       short element_1;       
       int *element_2;
    };
    #pragma pack(pop) 
    
  2. To check if the sizes of two structs are same during compilation use this trick

    char voidstr[(sizeof(struct1)==sizeof(struct2)) - 1]; //it will return error at compile time if this fail
    

OTHER TIPS

Your structures each include a long, which your platform apparently requires to be on a four-byte boundary. The structure must be at least as aligned as its most aligned member, so it has to be 4-byte aligned, and a structure's size has to be a multiple of its alignment in case it goes into an array.

Extra padding is required to make the long aligned, and so the smallest multiple of 4 is 16.

Two pieces of advice:

  • You can compute the offset of a field l1 by

     printf("Offset of field %s is %d\n", "l1", offsetof(struct pad, l1);
    

    To get the offsetof macro you will need to #include <stddef.h> (thanks caf!).

  • If you want to pack data as densely as possible, use unsigned char[4] instead of long and unsigned char[2] instead of short, and do the arithmetic to convert.


EDIT:: The sizeof(struct pad2) is 12. Your code has a bug; structure P2 is declared of type struct pad. Try this:

#define xx(T) printf("sizeof(" #T ") == %d\n", sizeof(T))
  xx(struct pad);
  xx(struct pad2);

P.S. I should definitely stop trying to answer SO questions after midnight.

On PS3, don't guess. Use __attribute__((aligned (16))), or similar. Not only does it guarantee that the start of the structure will be aligned on a proper boundary (if global or static), it also pads the structure to a multiple of your specified alignment.

Your code isn't showing what you think it is, because both P1 and P2 are defined as instances of struct pad. struct pad2 isn't ever used.

If I change the definition of P2 so that it is struct pad2, gcc does indeed decide to make it size 12.

struct pad P1;
printf("%d\n", sizeof(P1));

struct pad P2;
printf("%d\n", sizeof(P2));

P1 and P2 have the same type "struct pad" maybe you want to use "struct pad2" for P2.

All CPU expect that the built in data types like (int, float,char,double) are stored in the memory at their natural boundary, at address of their length.So structure padding is done to faster access of data from memory. For example, If int is declared, it should occurs in the memory at an address multiple of 4, as

size of the int is 4 byte.

Similarly for double, it resides in memory at multiple of 8.

If memory is properly aligned, CPU can run faster and work efficiently.

For the following examples, let us assume:

Sizeof(int)=4 byte

Sizeof(float)=4 byte

Sizeof(char)=1 byte

Find details on BoundsCheck

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top