问题
In other words: is it guaranteed that if I have an array allocated this way:
void *arr = calloc(nmemb, sizeof(some_type))
Then elta
, eltb
, eltc
will all point to the same location in memory, which will be the second element of type some_type
of this array?
some_type *elta = &((some_type*)arr)[1];
some_type *eltb = ((some_type*)arr)+1;
some_type *eltc = (char*)arr+sizeof(some_type);
The reason I’m asking this is because I’m trying to do a “container” in C, and if this doesn’t hold then I’m out of ideas how to return a pointer to any other element than the first one.
回答1:
Yes, it is guaranteed. If padding bytes are added, they are added within struct some_type
, but not in between two array elements.
E. g.:
struct S
{
int n;
short s;
// this is just for illustration WHERE byte padding (typically) would occur!!!
#if BYTE_ALIGNMENT >= 4
unsigned char : 0;
unsigned char : 0;
#endif
};
struct S s[2];
size_t d = (char*)(s + 1) - (char*)s;
With byte alignment adjusted to 4 or 8 (or even larger powers of 2), this struct will have size of 8 and d will be equally 8, with byte alignment set to 1 or 2, the struct will have size of 6 just as will be d...
Note: This is not the only place where padding bytes can occur: If you switched members n
and s
, padding bytes would be needed in between s
and n
to get n
correctly aligned. On the other hand, no padding bytes would be necessary after n any more as the structure size would assure correct alignment already.
Referring to the standard: C11, 6.2.5.20:
An array type describes a contiguously allocated nonempty set of objects with a particular member object type, called the element type. 36) Array types are characterized by their element type and by the number of elements in the array. [...]
(Highlighting by me!).
回答2:
Data alignment is a complex matter, as illustrated by the following example (that you can even draw to make your own experiments):
#include <stdio.h>
struct A { /* no padding */
char a[3];
};
struct B {
int a;
char b[3];
/* one byte of padding (in 32bit arch) added here */
};
struct C { /* no padding again */
char a[4];
char b[3];
};
struct D {
char a[3];
/* one byte of padding to ensure alignment of next field */
int b;
char c[3];
/* one byte of padding to ensure alignment of whole struct in arrays */
}
#define P(X) printf("sizeof struct %s == %ld\n", #X, sizeof (struct X))
int main()
{
P(A);
P(B);
P(C);
P(D);
} /* main */
As you see, the required alignment (1 byte) of the struct A
type is allowing to place it anywhere in memory and determines that no padding bytes are necessary to determine the sizeof
value.
In the second example, we introduced an int
value, which forces the whole struct
to be word aligned (so an int is accessible in a properly aligned memory address) so this time, the compiler has padded (at the end of the structure) for extra bytes, so any array type of the specified type gets correctly aligned, and its int
field is accessed at a valid address.
In the third example, I illustrate that the effect of the padding in the second example is due to the int
field present in the struct, as the third example has a same size field, but this time a non requiring alignment field, so no padding has been inserted, as all the individual data types inside need alignment of 1.
The output (on my system, a MAC OSX system) is:
sizeof struct A == 3
sizeof struct B == 8
sizeof struct C == 7
sizeof struct D == 12
来源:https://stackoverflow.com/questions/43766161/is-it-guaranteed-that-array-elements-in-c-will-be-stored-consecutively-with-no