tags:

views:

496

answers:

5

I heard a rumor that, in C, arrays that are contained inside structs may have padding added in between elements of the array. Now obviously, the amount of padding could not vary between any pair of elements or calculating the next element in an array is not possible with simple pointer arithmetic.

This rumor also stated that arrays which are not contained in structures are guaranteed to contain no padding. I know at least that part is true.

So, in code, the rumor is:

{
    // Given this:
    struct { int values[20]; } foo;
    int values[20];

    // This may be true:
    sizeof(values) != sizeof(foo.values);
}

I'm pretty certain that sizeof(values) will always equal sizeof(foo.values). However, I have not been able to find anything in the C standard (specifically C99) that explicitly confirms or denies this.

Does anyone know if this rumor is addressed in any C standard?

edit: I understand that there may be padding between the end of the array foo.values and the end of the struct foo and that the standard states that there will be no padding between the start of foo and the start of foo.values. However, does anyone have a quote from or reference to the standard where it says there is no padding between the elements of foo.values?

+1  A: 

Consider:

struct {
  short s;
  int i;
} s;

Assuming shorts are 16 bits and you're on 32 bits, the size will probably be 8 bytes as each struct members tends to be aligned a word (32 bit in this case) boundary. I say "probably" because it is implementation specific behaviour that can be varied by compiler flags and the like.

It's worth stressing that this is implementation behaviour not necessarily defined by the C standard. Much like the size of shorts, ints and longs (the C standard simply says shorts won't be larger than ints and longs won't be smaller than ints, which can end up as 16/32/32, 16/32/64, 32/32/64 or a number of other configurations).

cletus
In ARM-based machine it will do, but it is also very dangerous, as ARM does not perform alignment checks
Ignas Limanauskas
Actually, I believe on x86 and amd64 machines, that will have a size of 6, for gcc compilers -- there is no benefit for a char to be 8 byte aligned. But as you mention, this in compiler dependent.
Thanatos
The size is 8 on x86 and amd64 machines with gcc. I agree this is compiler dependent; in the example in this answer the issue is the natural alignment of an int.
janm
+1  A: 

Yes, sort of. Variables are often aligned to some boundry, depending on the variable. Take the following, for instance:

typedef struct
{
    double d;
    char c;
} a_type_t;

double and char are 8 and 1 bytes, on my system, respectively. Total of 9. That structure, however, will be 16 bytes, so that the doubles will always be 8-byte aligned. If I had just used ints, chars, etc, then the alignment might be 1, 2, 4, or 8.

For some type T, sizeof(T) may or may not equal sizeof(T.a) + sizeof(T.b) + sizeof(T.c) ... etc.

Generally, this is entirely compiler and architecture dependent. In practice, it never matters.

Thanatos
+1 for the most sensible example of all and for the last line. If this issue matters to someone, than someone is probably doing it wrong
Rom
+13  A: 

No, there will never be padding in between elements of an array. That is specifically not allowed. The C99 standard calls array types "An array type describes a contiguously allocated nonempty set of objects...". For contrast, a structure is "sequentially", not "contiguously" allocated.

There might be padding before or after an array within a structure; that is another animal entirely. The compiler might do that to aid alignment of the structure, but the C standard doesn't say anything about that.

Chris Arguin
Depends on what you mean. A compiler can add padding to the end of struct (see my example). If you take such a struct, and make an array of it, there are unused bytes between used bytes, but each element of the array is always sizeof(T) bytes after the previous one. But sizeof(T.a) + sizeof(T.b) + ... may not equal sizeof(T).
Thanatos
"The sizeof comparison you are making could pick that up" No? compair is between the two arrays, not between array and struct
Joakim Elofsson
@Joakim Ahh, I misread the sizeof. Thanks, I'll fix that.
Chris Arguin
@Thanatos - I basically agree, except that if the compiler adds bytes to the end of the structure, that is included in the sizeof. Sizeof is on a type, not an instance of that type, and the type doesn't know if it's used in an array or not.
Chris Arguin
Thanks for the quote. It comes from section 6.2.5 paragraph 20 for anyone interested in looking it up.
Whisty
+5  A: 

Careful here. Padding may be added at the end of the struct, but will not be added between the elements of the array as you state in your question. Arrays will always reference contiguous memory, though an array of structures may have padding added to each element as part of the struct itself.

In your example, the values and foo.values arrays will have the same size. Any padding will be part of the struct foo instead.

Dan Olson
+1  A: 

Here's the explanation as to why a structure may need padding between its members or even after its last member, and why an array doesn't:

Different types might have different alignment requirements. Some types need to be aligned on word boundaries, others on double or even quad word boundaries. To accomplish this, a structure may contain padding bytes between its members. Trailing padding bytes might be needed because the memory location directly ofter a structure must also conform to the structure's alignment requirements, ie if bar is of type struct foo *, then

(struct foo *)((char *)bar + sizeof(struct foo))

yields a valid pointer to struct foo (ie doesn't fail due to mis-alignment).

As each 'member' of an array has the same alignment requirement, there's no reason to introduce padding. This holds true for arrays contained in structures as well: If an array's first elment is correctly aligned, so are all following elements.

Christoph