0

Is it legal to use the address of the first member of a struct and use it like an array to access the different members?

Like:

struct Foo {
  int a, b, c;
}

Can I do

Foo f = {1, 2, 3};
int *fPtr = &f.a;
int res = fPtr[1]; // access to b

?

Or is it undefined behavior?

And is it equivalent to:

Foo f = {1, 2, 3};
int *fPtr = reinterpret_cast<int *>(f);
int res = fPtr[1];

?

And is this one undefined behavior?

Jojolatino
  • 696
  • 5
  • 11
  • 1
    Why would you do this? – Nathan Pierson May 23 '21 at 17:30
  • 4
    It's undefined behavior. If nothing else, there's a practical matter of padding; the compiler is allowed to insert some between members. – Igor Tandetnik May 23 '21 at 17:31
  • @NathanPierson I want to iterate over the x, y, z, w members of a 4th dimensional vector – Jojolatino May 23 '21 at 17:39
  • 1
    I'd recommend making a question about doing that, then. – Nathan Pierson May 23 '21 at 17:41
  • It is technically undefined behavior. I would rather use a union like `union Foo{int arr; struct {int x, y, z, w};};`. This still breaks strict aliasing rule, but all compilers handle aliasing correctly when inside a `union`. – prapin May 23 '21 at 18:06
  • 1
    @prapin -- it's true that with that union, `arr` and `x` will be in the same location. That does not mean that `&arr+1` will point at `y`. As mentioned in another note, there can be padding between `x`, `y`, `z`, and `w` that's different from the padding in an array. This isn't a matter of "handl[ing] aliasing correctly", but of what guarantees you have that two **different** data structures will have **the same** layout. In general, there is no guarantee, even if you think they look sort of alike. – Pete Becker May 23 '21 at 18:24
  • @PeteBecker For the size guarantee, I would put a `static_assert` on the expected `struct` size. Anyway, structure padding is implementation defined, one can always check the ABI for the platform. – prapin May 23 '21 at 19:16
  • 1
    @prapin -- it isn't implementation-defined. It's implementation specific. Implementation defined means that a conforming implementation must document what it does. Yes, you can make educated guesses here, but don't forget that many command-line settings can affect structure layout, and if you're going to try to write reliable code you have to allow for all possible variations. Asserting on the size of the struct doesn't address the issue. It's about internal padding, not total size. Yes, you can guess that if it's the size you expect it's laid out the way you expect. But that's still guessing. – Pete Becker May 23 '21 at 19:21
  • @PeteBecker: Unfortunately, the Standard lumps together under the category "undefined behavior" all actions for which some implementations might not be able to practically specify a behavior, including many actions which they thought most implementations should be expected to process identically. It further makes no attempt to distinguish actions like "access element `i` of `sometstruct.array`" or "Add `i` (scaled if needed) to the address of someStruct.array and access whatever is there", on the assumption that implementations would select whichever of those would better serve users' needs. – supercat May 24 '21 at 17:46

0 Answers0