#include <stdio.h>
struct Obj {
char a;
uint32_t b;
uint8_t c;
uint64_t d[0];
};
struct Obj1 {
uint64_t d[0];
};
int main() {
uint64_t a[0];
printf("%d\n", sizeof(Obj)); // 16
printf("%d\n", sizeof(a)); // 16
printf("%d\n", sizeof(Obj1)); // 16
//cout << sizeof(Obj) << endl; // 16
//cout << sizeof(a) << endl; // 0
//cout << sizeof(Obj1) << endl; // 0
}
As shown above, why the uint64_t
variable within the struct will not be stacked right back after the uint8_t
, and more peculiar is that the empty array has zero sizes outside the structure.
It's actually an interview question. The explanation goes like this, though still can't understand.
If there is no fourth field, it should be 4+4+4=12, plus the fourth field is 16, the fourth field does not occupy space, but it will tell the compiler to align by 8 bytes
This usage is often used in the kernel, for example, the following can be directly accessed by subscript
Obj o1; uint64_t array[1024]; // In memory, array immediately follows
o1 o1.d[123]; // can access the elements of array
As noted by comments, this may be only applied in C instead of C++. SO I changed the code to C version.
This interview question probes a candidates knowledge of alignment and certain semantics in both the C standard and specific implementations.
The char a
member has size one (byte) and alignment requirement one (byte).
The uint32_t b
member has size four and commonly has an alignment requirement of four bytes. In order to place it on an address that is a multiple of four bytes, the compiler has to include three unused bytes after a
and before b
, which are calling padding bytes. Up to this point, the structure requires 1+3+4 = 8 bytes.
The uint8_t c
member has size one and alignment requirement one. Up to this point, the structure requires 9 bytes.
With uint64_t d[0]
, the behavior is not defined by the C standard. However, unless the interviewer has specified this is a question about strictly conforming standard C, answering that the behavior is undefined is inadequate, as there is more to C than just the standard. There is also conforming (but not strictly conforming) C and non-standard variants of C. GCC supports a well-known extension in which the last member of a structure may be declared as an array with zero elements, and the interviewer expects the questioner to be aware of this.
When such a structure is used, the program must allocate sufficient space for whatever array elements it wishes to use, by adding such space to the request made with malloc
or a similar memory-allocation routine. For example, to allocate space for the base structure plus 13 elements, one might use malloc(sizeof(struct Obj) + 13 * sizeof(uint64_t))
.
Commonly, a uint64_t
has an alignment requirement of eight bytes. Whatever its alignment requirement is, the compiler will add sufficient unused bytes between members c
and d
to ensure d
has the proper alignment. If it does require eight-byte alignment, then seven bytes must be inserted after c
, so the structure size up to the start of d
will be 1+3+4+1+7 = 16 bytes.