Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this a portable way to make a stack buffer eight-byte aligned?

Tags:

c

struct {
  uint64_t a; char z[120];
} b;

...

struct buffer_with_alignment_requirement* c = (struct buffer_w*)&b;
c->start_using_it;

Without the first member a, we might crash when accessing fields in the buffer. Is it portable and correct to simply add a member like this to force aligment for the whole struct to be strict enough?

This is not a question about pointer aliasing, simply about whether the address of b on the stack is always eight-byte aligned.

like image 441
Nicholas Wilson Avatar asked May 02 '13 12:05

Nicholas Wilson


1 Answers

The exact-width integer types, if they exist (7.20.1.1p3), do not have any particular alignment requirements other than that they should be at least as aligned as char and no more aligned than max_align_t (6.2.8p2-4). There is not even any requirement that alignment should follow integer conversion rank, except of course that corresponding signed and unsigned types should have the same alignment (6.2.5p6).

If you want a particular alignment, use an alignment specifier:

#include <stdalign.h>
struct alignas(8) {
  char z[120];
} b;

However, presumably given your description of accessing fields, what you actually want is for the buffer to be aligned to the most aligned type that could exist within the buffer. To do this C11 provides max_align_t; in older compilers you can emulate max_align_t using a union of the standard types:

typedef union {
  char c;
  short s;
  int i;
  long l;
  long long ll;  // if available
  float f;
  double d;
  long double ld;  // if available
  void *p;
  void (*fun)();
} max_align_t;
like image 142
ecatmur Avatar answered Sep 28 '22 18:09

ecatmur