C (++) struct force extra padding

I have seen countless questions on the “I don’t like filling out how to disable it” form, but have not yet found anything on how to get the compiler to provide an additional add-on.

A specific case that I have is similar to

struct particle{ vect2 s; vect2 v; int rX; int rY; double mass; int boxNum; }; 

Where vect2 is a simple struct {double x; double y;} vect2 struct {double x; double y;} vect2 . To use SSE2, I need to be able to load a pair of doubles aligned on 16-byte boundaries. This worked until I added an extra int , pushing my structure size from 48 to 56 bytes. The result is segfaults.

Is there some kind of compiler directive I can use that either says: “Put this structure to make it a 16 byte multiplicity”, or “does this structure have 16-byte alignment”? I know that I can do this manually (for example, on an additional char [12]), but I would just tell the compiler (GCC, preferably compatible with ICC), and I do not need to do this manually if I change the structure in the future.

+8
c ++ c gcc struct memory-alignment
source share
5 answers

I am adding my own answer to this question if someone finds a solution. Mark's solution is neat and fulfills an automatic requirement, but not when I finished work. I wanted to avoid this, so I asked a question, but there is a “trivial” solution:

 struct particle{ vect2 s; vect2 v; int rX; int rY; double mass; int boxNum; char padding[12]; }; 

Manually checking the current size of the struct , you can add the appropriate number of characters (or anything else, but char do it in bytes) to make it correct. This showed better performance as well as simplicity, although it does require updating every time the structure is changed. In this case, this is normal, although if you had a structure that could resize depending on the parameters, that would be problematic.

Note that my struct was 56 bytes, and I added 12 to make it 64. This math does not work because the final int already padded with 4 bytes to the 8-byte boundary; struct was actually only 52 bytes before. Adding only 5 char would work by making a struct length of 57 bytes that would be padded to 64, but this is not such a nice solution, so I used 12 to make it work exactly.

+3
source share

You can attach two structures to automatically lay it, without thinking about what size you yourself.

 struct particle { // ... }; { particle p; char padding[16-(sizeof(particle)%16)]; }; 

This version, unfortunately, adds 16 bytes if the structure is already a multiple of 16. This is inevitable because the standard does not allow arrays of zero length.

Some compilers allow zero-length arrays as an extension, in which case you can do this instead:

 struct particle_wrapper { particle p; char padding[sizeof(particle)%16 ? 16-(sizeof(particle)%16) : 0]; }; 

This version does not add padding bytes if the structure is already a multiple of 16.

+8
source share

In gcc you can align arbitrary types and variables with __attribute__((aligned(...))) . For your example, it will be

 struct particle{ vect2 s; vect2 v; int rX; int rY; double mass; int boxNum; } __attribute__((aligned (16))); 

This automatically completes the structure so that its arrays are correctly aligned.

+3
source share

The new C ++ 11 specification also has a new feature , although I do not believe that many vendors are already implemented.

You can try the package pragma, although it is not supported by the specification. Both GCC and MS support this, though.

This aligns the structure at 1 byte boundaries, although you can change the number to whatever you want.

 #pragma pack(push,1) // ... #pragma pack(pop) 

update:

Thus, it is obvious that the foregoing will not work, since it only reduces the filling, never expanding it. Unfortunately, today I do not have a test environment.

Perhaps using an anonymous union will work. I know that it will expand to the largest size, although I do not know if you will receive any guarantees regarding alignment otherwise.

 template<typename T, size_t padding_size> struct padded_field { union { T value; uint8_t padding[padding_size]; }; }; 
+1
source share

Not tested, but this may work:

 #include <xmmintrin.h> struct particle{ union { vect2 s; __m128 s_for_alignment; }; union { vect2 v; __m128 v_for_alignment; }; ... }; 

I know that gcc previously correctly aligned __m128 , but now they should be fixed.

+1
source share

All Articles