Is it legal to index into a struct?

后端 未结 10 1815
悲哀的现实
悲哀的现实 2020-11-30 01:12

Regardless of how \'bad\' the code is, and assuming that alignment etc are not an issue on the compiler/platform, is this undefined or broken behavior?

If I have a s

10条回答
  •  佛祖请我去吃肉
    2020-11-30 02:12

    This is undefined behavior.

    There are lots of rules in C++ that attempt to give the compiler some hope of understanding what you are doing, so it can reason about it and optimize it.

    There are rules about aliasing (accessing data through two different pointer types), array bounds, etc.

    When you have a variable x, the fact that it isn't a member of an array means that the compiler can assume that no [] based array access can modify it. So it doesn't have to constantly reload the data from memory every time you use it; only if someone could have modified it from its name.

    Thus (&thing.a)[1] can be assumed by the compiler to not refer to thing.b. It can use this fact to reorder reads and writes to thing.b, invalidating what you want it to do without invalidating what you actually told it to do.

    A classic example of this is casting away const.

    const int x = 7;
    std::cout << x << '\n';
    auto ptr = (int*)&x;
    *ptr = 2;
    std::cout << *ptr << "!=" << x << '\n';
    std::cout << ptr << "==" << &x << '\n';
    

    here you typically get a compiler saying 7 then 2 != 7, and then two identical pointers; despite the fact that ptr is pointing at x. The compiler takes the fact that x is a constant value to not bother reading it when you ask for the value of x.

    But when you take the address of x, you force it to exist. You then cast away const, and modify it. So the actual location in memory where x is has been modified, the compiler is free to not actually read it when reading x!

    The compiler may get smart enough to figure out how to even avoid following ptr to read *ptr, but often they are not. Feel free to go and use ptr = ptr+argc-1 or somesuch confusion if the optimizer is getting smarter than you.

    You can provide a custom operator[] that gets the right item.

    int& operator[](std::size_t);
    int const& operator[](std::size_t) const;
    

    having both is useful.

提交回复
热议问题