views:

989

answers:

6

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: http://pastebin.com/f2b8e7788

+3  A: 

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.

Norman Ramsey
Or you could use offsetof(struct pad, l1) :)
caf
Oh, and 12 is a multiple of 4 too, so that doesn't actually explain it.
caf
Really! Sorry for my buggy code, it was near the morning...
makos
+1  A: 

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.

Dan Olson
I thinks there may be some problem with the boundaries, when somebody want to transfer data between PPE and SPE below 16 byte. This guarantee may cause hazard between addresses. -but exactly I don't know. What do you think?
makos
As long as things are 16 byte aligned on both ends it will still work, but you get better speed if you can 128 byte align both sides. I'm not sure exactly why, it's just a rule of thumb to 128 byte align buffers that receive DMA for us.
Dan Olson
+1  A: 

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.

caf
Congratulations, you're the first one to get this right - God, it took a while for someone to do that! :)
Pavel Minaev
it's friday .
Luca Matteis
+1  A: 
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.

Nicolas Viennot
Good spotting of the obvious (once spotted)!
Jonathan Leffler
+2  A: 

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
    
ralu
A: 

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

Boundscheck