The C11 standard section 6.2.5.20 defines array as:
An array type describes a contiguously allocated nonempty set of objects with a particular member object type, called the element type.
while struct is defined as:
A structure type describes a sequentially allocated nonempty set of member objects (and, in certain circumstances, an incomplete array), each of which has an optionally specified name and possibly distinct type.
The 6.7.2.1 section says that padding could be inserted between fileds:
Each non-bit-field member of a structure or union object is aligned in an implementation- defined manner appropriate to its type.
Within a structure object, the non-bit-field members and the units in which bit-fields reside have addresses that increase in the order in which they are declared. A pointer to a structure object, suitably converted, points to its initial member (or if that member is a bit-field, then to the unit in which it resides), and vice versa. There may be unnamed padding within a structure object, but not at its beginning.
But does this all mean that the following objects could have different memory layouts?
struct A {
char x0;
short x1;
};
struct B {
struct A x0;
struct A x1;
struct A x2;
};
assert(sizeof(struct B) == sizeof(struct A[3]));
I created this test script to check the memory layout for GCC:
import itertools
import subprocess
src = """
#include "assert.h"
struct A {
{fields}
};
struct B {
struct A x0;
struct A x1;
struct A x2;
};
int main(int argc, char** argv) {
assert(sizeof(struct B) == sizeof(struct A[3]));
return 0;
}
"""
def main():
all_types = ["char", "short", "int", "long long"]
for types in itertools.product(all_types, repeat=3):
rendered = src.replace("{fields}", "".join([
" {} x{};\n".format(t, i)
for i, t in enumerate(types)]))
with open("main.c", "w") as f:
f.write(rendered)
subprocess.call(["gcc", "main.c"])
subprocess.call(["./a.out"])
if __name__ == "__main__":
main()
But GCC always produces the same memory layout for the array and the structure.
- Are there any real world examples when the layout is different?
- Is is safe to cast such structure instance to the array?
- Would it be safer with union?