3

I have a structure:

struct foo {
  struct {
     int a;
     int b;
     long len;
     unsigned short c;
     unsigned short d;
  };
  char payload[1024];
} bar;

I want to find out, at configure time, if I need to insert padding to make 'payload' double-aligned.

Autoconf provides AC_CHECK_SIZEOF(type) and AC_CHECK_ALIGNOF(type), but what I really need is something like AC_CHECK_OFFSETOF(type, member). If the reported offset was not double-aligned, I could introduce enough padding to make it so.

I could run a little test program that reported offsetof(struct bar, payload), but I don't want to introduce a run-time check into my build system (we cross-compile not infrequently).

Rob Latham
  • 5,085
  • 3
  • 27
  • 44

3 Answers3

1

You can use AC_COMPUTE_INT:

AC_COMPUTE_INT([payload_offset], [offsetof(struct bar, payload)], ...)

But it would probably be easier just to use an anonymous union to force alignment:

struct foo {
  struct {
     int a;
     int b;
     long len;
     unsigned short c;
     unsigned short d;
  };
  union {
    char payload[1024];
    double dummy; /* for alignment */
  };
} bar;

If you don't want to use a union, you can compute the padding in place:

struct foo {
  struct header {
     int a;
     int b;
     long len;
     unsigned short c;
     unsigned short d;
  };
  char padding[(alignof(double) - 1) - ((sizeof(struct header)
      + alignof(double) - 1) % alignof(double))];
  char payload[1024];
} bar;
ecatmur
  • 152,476
  • 27
  • 293
  • 366
  • Of the two approaches, zero-width bitfields or stashing into a union, which one is the more standard way, if one can say such a thing, to do so? – Rob Latham Nov 01 '13 at 17:47
  • 1
    @RobLatham a zero-width bitfield can force padding to the alignment of an integral type, but not a floating-point type. Anonymous unions are part of the standard (6.7.2.1p13) as of C11, and have wide support. – ecatmur Nov 01 '13 at 17:59
  • we still try pretty hard to maintain c89, but maybe a named union will work. – Rob Latham Nov 01 '13 at 19:59
  • Thanks for your answer. I chose the zero-width bitfield approach since it's available in older c environments. – Rob Latham Nov 01 '13 at 21:55
1

Using a zero length bitfield might solve this problem without autotool tricks.

struct foo {
  struct {
     int a;
     int b;
     long len;
     unsigned short c;
     unsigned short d;
  };
  int64_t : 0; // or long long whatever integer type is sizeof(double)
  char payload[1024];
} bar;
Community
  • 1
  • 1
ldav1s
  • 15,885
  • 2
  • 53
  • 56
0

I don't really think that autoconf can tell you that, as it is a matter of the compiler who decides to add padding or not. So I would think that the only reasonable way would be to compile a program that checks if offset of the member equals to what you think it should be equal.

Artem Shinkarov
  • 379
  • 2
  • 5
  • no doubt the answer is entirely up to the compiler. AC_CHECK_SIZEOF and AC_CHECK_ALIGNOF determine the answer exactly as you suggest: by compiling a program. The trick I'm missing is how to get the answer without running that program. – Rob Latham Nov 01 '13 at 17:49
  • Well, use a static assert then, that would break a program at the compile time. Something like: char x [(expr) ? 1 : -1]; – Artem Shinkarov Nov 01 '13 at 17:54