3

Is there anyway to make gcc pad only at the end of a packed structure?

I am using a packed structure for space optimization, but also use that struct to compute memory offsets (storing multiple structs in a buffer). Therefore if the total size of my struct is not aligned (not a multiple of 4 let's say), if I try to access the following struct in my buffer I will get a SIGBUS.

E.g.

sizeof(my_packed_struct) == 11
sizeof(other_struct) == 12

If I put a my_packed_struct at address 0x2000, I would also put other_struct at 0x200B (+11 bytes).

So if I want to access the other_struct, e.g. (other_struct*)0x200B, I would get a SIGBUS.

So I'm curious if there's a way to make GCC pad the structure to avoid this problem.

Here is the definition:

typedef struct __attribute__ ((packed)) my_packed_struct {
    uint8_t att1;
    bool att2;
    uint32_t att3;
    uint32_t att4;
    bool att5;
} my_packed_struct;

I could just add an attribute like

typedef struct __attribute__ ((packed)) my_packed_struct {
    uint8_t att1;
    bool att2;
    uint32_t att3;
    uint32_t att4;
    bool att5;
    uint8_t pad;
} my_packed_struct;

To make sure to match to size 12, but I'm looking for a solution where I wouldn't have to compute the size and pad manually (e.g. if I have to add another attribute in the future).

I had a look at memory alignment within gcc structs, I do store the struct in a buffer internally, but I still need to expose a struct for convenience and client use.

Community
  • 1
  • 1
joetde
  • 1,556
  • 1
  • 16
  • 26
  • `... for space optimization,` To start with: don't use bool. And put the bool&char fields at adjacent positions, so that they will only need alignment just once. – wildplasser Feb 15 '17 at 16:57
  • I assume this is for an embedded system, or you really would not have to save just a few bytes, even if you create millions of the structures. As for your problem, do the `other_struct` *have* to follow directly after the packed structure? Why not put it at a nicely aligned address after the packed structure? Then the padding will be the empty space between the two structures. – Some programmer dude Feb 15 '17 at 17:02
  • Oh and another thing, you probably put the `other_structure` at `0x200B` right? Otherwise you have an overlap. – Some programmer dude Feb 15 '17 at 17:03
  • Add a pad bye manually? – Jonathan Leffler Feb 15 '17 at 17:05
  • @Someprogrammerdude yes it's for an embedded system, and yes you're right, it 0x200B. other_struct has to follow the other structure (basically header/payload). Also, I don't want to put the burden on the writer to align the structures. – joetde Feb 15 '17 at 19:01
  • Possible duplicate of [memory alignment within gcc structs](http://stackoverflow.com/questions/2554229/memory-alignment-within-gcc-structs) – Alex Feb 15 '17 at 20:25

1 Answers1

1

What about this trick

union __attribute__ ((packed)) struct_union
{
    struct my_packed_struct data;
    int pad[(sizeof(my_packed_struct)+3)/sizeof(int)];
} struct_union;

and use struct_union instead of my_packed_struct directly?

Why it will work?

  1. union is packed so it will not be extra padded
  2. pad will always be multiple of 4 (because of int)
  3. sizeof calculation will make sure it is big enough to hold whole my_packed_struct
Anty
  • 1,486
  • 1
  • 9
  • 12
  • You should replace `3` with `sizeof(int) - 1` (or whatever the source of 3 is) – M.M Feb 15 '17 at 21:45
  • Yes - 3 is sizeof(int)-1. int could be replaced there with other types too - but the question was about 4 byte alignment. – Anty Feb 15 '17 at 21:50