On Tue, Oct 20, 2015 at 10:10:44PM +0000, Joseph Myers wrote: > > typedef struct FA5_7 { > > int i; > > char a5_7 [5][7]; > > } FA5_7; > > > > __builtin_offsetof (FA5_7, a5_7 [0][7]), // { dg-warning > > "index" } > > __builtin_offsetof (FA5_7, a5_7 [1][7]), // { dg-warning > > "index" } > > __builtin_offsetof (FA5_7, a5_7 [5][0]), // { dg-warning > > "index" } > > __builtin_offsetof (FA5_7, a5_7 [5][7]), // { dg-warning > > "index" } > > > > Here I think the last one of these is most likely invalid (being 8 bytes > > past > > the end of the object, rather than just one) and the others valid. Can you > > confirm this? (If the &a.v[2].a example is considered invalid, then I think > > the a5_7[5][0] test would be the equivalent and ought to also be considered > > invalid). > > The last one is certainly invalid. The one before is arguably invalid as > well (in the unary '&' equivalent, &a5_7[5][0] which is equivalent to > a5_7[5] + 0, the questionable operation is implicit conversion of a5_7[5] > from array to pointer - an array expression gets converted to an > expression "that points to the initial element of the array object", but > there is no array object a5_7[5] here).
C11, 6.5.2.1/3: Successive subscript operators designate an element of a multidimensional array object. If E is an n-dimensional array (n >= 2) with dimensions i x j x . . . x k, then E (used as other than an lvalue) is converted to a pointer to an (n - 1)-dimensional array with dimensions j x . . . x k. If the unary * operator is applied to this pointer explicitly, or implicitly as a result of subscripting, the result is the referenced (n - 1)-dimensional array, which itself is converted into a pointer if used as other than an lvalue. It follows from this that arrays are stored in row-major order (last subscript varies fastest). As far as I see, a5_7[5] here is never treated as an array, just as a pointer, and &a5_7[5][0] is valid. Segher