Is the following well defined, for different values of REF
?
#include
#define REF 1
#define S 1
int main(void) {
int a[2][S
Given
int blah(int x, int y)
{
int a[2][5];
a[1][0] = x;
a[0][y] = 9;
return a[1][0];
}
nothing in the Standard would forbid a compiler from recoding that as int blah(int x, int y) { return x; }
, nor trapping (or doing anything whatsoever) when y>=5
, since a[0]
and a[1]
are distinct arrays of five elements each. In cases where the last element of an indirectly-accessed structure is a single-element array, compilers have generally included code to allow pointer arithmetic on that array to yield a pointer to storage outside the structure. While such pointer arithmetic would be forbidden by the Standard, it enables useful constructs which could not be practically implemented in any standard-compliant fashion prior to C99.
Note that adding 5 to a[0]
would yield an int*
that compares identical to a[1]
, but the fact that a "one-past" pointer compares equal to a pointer which identifes the next object in memory does not imply that it may be safely used to access the latter object. Such accesses may often work, but that doesn't mean compilers are required to have them do so.
Can a copy of the bit pattern of a pointer point semantically to an object when the original only physically does?
There is no such distinction effectively, because a[0] + S
is the same as a[1]
, assuming that inner array is declared with S
size.
The following:
int a[2][S];
declares two-elements array, where each element is an array of S
-elements of type int
. Arrays are stored contigously and there is no padding before/between/after its elements.
We will prove, that a[0] + S == a[1]
holds. It can be rewritten as:
*(a + 0) + S == *(a + 1)
By pointer arithmetic, RHS adds 1 * sizeof(*a)
bytes to a
, that is the same as size of the inner array. LHS is little more complex, as addition is performed after dereference of a
, thus it adds:
S * sizeof(**a)
bytes,
Both sides are guaranteed to be equal when they point to the same object (the same memory location), of the same type. Hence you could rewrite it into "absolute" one-byte form as:
(char *)a + S * sizeof(**a) == (char *)a + sizeof(*a)
This reduces into:
S * sizeof(**a) == sizeof(*a)
We know, that sub-array *a
has S
elements of type of **a
(i.e. int
), so both offsets are the same. Q.E.D.