8

Recently I came across the following snippet, which is an attempt to ensure all bytes of i (nad no more) are accessible as individual elements of c:

union {
  int i;
  char c[sizeof(int)];
};

Now this seems a good idea, but I wonder if the standard allows for the case where the alignment requirements for char are more restrictive than that for int.

In other words, is it possible to have a four-byte int which is required to be aligned on a four-byte boundary with a one-byte char (it is one byte, by definition, see below) required to be aligned on a sixteen-byte boundary?

And would this stuff up the use of the union above?

Two things to note.

  1. I'm talking specifically about what the standard allows here, not what a sane implementor/architecture would provide.

  2. I'm using the term "byte" in the ISO C sense, where it's the width of a char, not necessarily 8 bits.

timrau
  • 22,578
  • 4
  • 51
  • 64
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953

2 Answers2

7

No type can ever have stricter alignment requirements than its size (because of how arrays work), and sizeof(char) is 1.

In case it's not obvious:

  • sizeof(T [N]) is sizeof(T)*N.
  • sizeof is in units of char; all types are represented as a fixed number of bytes (char), that number being their size. See 6.2.6 (Representation of Types) for details.
  • Given T A[2];, (char *)&A[1] - (char *)&A[0] is equal to sizeof A[0].
  • Therefore the alignment requirement for T is no greater than sizeof(T) (in fact it divides sizeof(T))
R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • You'll need to cite ISO to convince me on that one, R. What particular feature of arrays wouldn't work if you automatically scaled the `a[i]` and `a+i` using the alignment rather than the size? – paxdiablo Dec 21 '10 at 05:30
  • @paxdiablo: Then this wouldn't work. `(void *) a + i * sizeof(*a)` – Bill Lynch Dec 21 '10 at 05:39
  • 1
    @sharth - That doesn't work anyway - pointer arithmetic on `void *` isn't allowed. – Chris Lutz Dec 21 '10 at 05:41
  • Whoops. I didn't realize that. gcc apparently only warns about that with pedantic. But that still should be valid if I cast to a uint8_t. – Bill Lynch Dec 21 '10 at 05:43
  • @sharth - `uint8_t` is going to be a `typedef` for `unsigned char`. Same alignment issues. – Chris Lutz Dec 21 '10 at 05:46
  • 2
    @paxdiablo: Read 6.2.6 Representation of Types. All types are represented in units of `char`. The size of an array is the number of elements times the size of the element type. Etc. etc. etc. This is all very basic. – R.. GitHub STOP HELPING ICE Dec 21 '10 at 05:50
  • @sharth: The type you want is `char *`, not `void *`. The standard guarantees the behavior you want for `char *`. – R.. GitHub STOP HELPING ICE Dec 21 '10 at 05:57
  • 1
    @pax Arrays can't have padding and must be contiguous per the standard. Therefore what R said is exactly right – SiegeX Dec 21 '10 at 06:41
2

Have a look at this thread. There, I questioned the usefulness of C Unions and there are some interesting insights. The important thing is that the Standard does not ensure the alignment of the different fields at all!

EDIT: paxdiablo, just noticed you were one of the guys answering that question, so you should probably be familiar with this limitation.

Community
  • 1
  • 1
ysap
  • 7,723
  • 7
  • 59
  • 122