Is it legal to index into a struct?

后端 未结 10 1801
悲哀的现实
悲哀的现实 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:06

    It is illegal 1. That's an Undefined behavior in C++.

    You are taking the members in an array fashion, but here is what the C++ standard says (emphasis mine):

    [dcl.array/1]: ...An object of array type contains a contiguously allocated non-empty set of N subobjects of type T...

    But, for members, there's no such contiguous requirement:

    [class.mem/17]: ...;Implementation alignment requirements might cause two adjacent members not to be allocated immediately after each other...

    While the above two quotes should be enough to hint why indexing into a struct as you did isn't a defined behavior by the C++ standard, let's pick one example: look at the expression (&thing.a)[2] - Regarding the subscript operator:

    [expr.post//expr.sub/1]: A postfix expression followed by an expression in square brackets is a postfix expression. One of the expressions shall be a glvalue of type “array of T” or a prvalue of type “pointer to T” and the other shall be a prvalue of unscoped enumeration or integral type. The result is of type “T”. The type “T” shall be a completely-defined object type.66 The expression E1[E2] is identical (by definition) to ((E1)+(E2))

    Digging into the bold text of the above quote: regarding adding an integral type to a pointer type (note the emphasis here)..

    [expr.add/4]: When an expression that has integral type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the expression P points to element x[i] of an array object x with n elements, the expressions P + J and J + P (where J has the value j) point to the (possibly-hypothetical) element x[i + j] if 0 ≤ i + j ≤ n; otherwise, the behavior is undefined. ...

    Note the array requirement for the if clause; else the otherwise in the above quote. The expression (&thing.a)[2] obviously doesn't qualify for the if clause; Hence, Undefined Behavior.


    On a side note: Though I have extensively experimented the code and its variations on various compilers and they don't introduce any padding here, (it works); from a maintenance view, the code is extremely fragile. you should still assert that the implementation allocated the members contiguously before doing this. And stay in-bounds :-). But its still Undefined behavior....

    Some viable workarounds (with defined behavior) have been provided by other answers.



    As rightly pointed out in the comments, [basic.lval/8], which was in my previous edit doesn't apply. Thanks @2501 and @M.M.

    1: See @Barry's answer to this question for the only one legal case where you can access thing.a member of the struct via this parttern.

提交回复
热议问题