Home > OS >  How to align but with offset
How to align but with offset

Time:06-14

Say I need to allocate struct A but b needs to be 4 aligned.

struct A
{
    char a;
    char b[42];
};

I guess I can manually pad a pointer returned by malloc(). Any cleaner way? Like gcc's __attribute__((aligned(4))) but that aligns the whole structure. And I can't change it's layout.

CodePudding user response:

You can use alignas(<alignment>) on the structure member you want to align. This implies that struct and union types will get an alignment equal to the largest alignment of any member, and will insert padding between elements (and array entries) to ensure that the necessary alignment is provided.

For compiler-allocated data (static or stack) this is all you need to do.

For C11, for any dynamically allocated data you still need to ensure that the base pointer of the allocation is suitably aligned - malloc doesn't guarantee much more than "enough for the longest native type". In your case with alignas(4) malloc would likely fit in the longest native type so malloc would be OK, but in the general case you might need manually calculated padding if over-aligning (e.g. for SIMD vector loads).

If you want standard support for this you need to fast-forward to C 17, which adds a number of memory allocators that take alignment as a parameter. These allocators are used specifically for over-aligned types. Also C 17 guarantees any allocations from new are sufficiently aligned for alignof(std::max_align_t) by default.

CodePudding user response:

With standard C you can use the keyword _Alignas (or the macro alignas from stdalign.h):

struct A
{
  _Alignas(4) char a;
  _Alignas(4) char b[42];
};

This consequently makes a occupy 4 bytes and b 44 bytes. Example:

#include <stdio.h>
#include <stddef.h>

struct A
{
  char a;
  char b[42];
};

struct B
{
  _Alignas(4) char a;
  _Alignas(4) char b[42];
};

int main (void)
{
  printf("Size A: %zu\n", sizeof(struct A));
  printf("Offset A.a: %zu\n", offsetof(struct A,a));
  printf("Offset A.b: %zu\n", offsetof(struct A,b));

  printf("Size B: %zu\n", sizeof(struct B));
  printf("Offset B.a: %zu\n", offsetof(struct B,a));
  printf("Offset B.b: %zu\n", offsetof(struct B,b));
}

Output:

Size A: 43
Offset A.a: 0
Offset A.b: 1
Size B: 48
Offset B.a: 0
Offset B.b: 4
  • Related