Are struct names pointers to first element?

2020-04-16 18:00发布

问题:

I found a few similar questions but none of them helped much. Are struct names pointers to the first element of the struct, similar to an array?

struct example {
    int foo;
    int bar;
};

struct example e;
e.foo = 5;
e.bar = 10;
printf("%d\n%d\n%d\n%d\n%d\n%d\n", e, e.foo, e.bar, &e, &e.foo, &e.bar);

Output:

5
5
10
2033501712
2033501712
2033501716

All of the answers to the other questions said "no", but this output confuses me. All help would be greatly appreciated.

回答1:

The address of a struct is indeed the address of the first element, though you'll need to know the type of the element in order to safely cast it.

(C17 §6.7.2.1.15: "A pointer to a structure object, suitably converted, points to its initial member ... and vice versa. There may be unnamed padding within as structure object, but not at its beginning.")

While it's kind of ugly, numerous pieces of production software rely on this. QNX, for example, uses this kind of behavior in open control block (OCB) logic when writing resource managers. Gtk also something similar.

Your current implementation is dangerous though. If you must rely on this behavior, do it like so, and don't attempt to pass a pointer-to-struct as an argument to printf(), as you're intentionally breaking a feature of a language with minimal type-safety.

struct example {
    int foo;
    int bar;
};

struct example myStruct = { 1, 2 };
int* pFoo = (int*)&myStruct;
printf("%d", *pFoo);

Finally, this only holds for the first element. Subsequent elements may not be situation where you expect them to be, namely due to struct packing and padding.



回答2:

struct names aren't pointers to anything. You are invoking undefined behaviour by passing a struct to printf with an incompatible format specifier %d. It may seem to "work" because the first member of the struct has the same address as the struct itself.