Accesing a 2D array using a single pointer Accesing a 2D array using a single pointer arrays arrays

Accesing a 2D array using a single pointer


The array who's base address (pointer to first element) p is assigned is of type int[2]. This means the address in p can legally be dereferenced only at locations *p and *(p+1), or if you prefer subscript notation, p[0] and p[1]. Furthermore, p+2 is guaranteed to be a legally evaluated as an address, and comparable to other addresses in that sequence, but can not be dereferenced. This is the one-past address.

The code you posted violates the one-past rule by dereferencing p once it passes the last element in the array in which it is homed. That the array in which it is homed is buttressed up against another array of similar dimension is not relevant to the formal definition cited.

That said, in practice it works, but as is often said. observed behavior is not, and should never be considered, defined behavior. Just because it works doesn't make it right.


The object representation of pointers is opaque, in C. There is no prohibition against pointers having bounds information encoded. That's one possibility to keep in mind.

More practically, implementations are also able to achieve certain optimizations based on assumptions which are asserted by rules like these: Aliasing.

Then there's the protection of programmers from accidents.

Consider the following code, inside a function body:

struct {    char c;    int i;  } foo;char * cp1 = (char *) &foo;char * cp2 = &foo.c;

Given this, cp1 and cp2 will compare as equal, but their bounds are nonetheless different. cp1 can point to any byte of foo and even to "one past" foo, but cp2 can only point to "one past" foo.c, at most, if we wish to maintain defined behaviour.

In this example, there might be padding between the foo.c and foo.i members. While the first byte of that padding co-incides with "one past" the foo.c member, cp2 + 2 might point into the other padding. The implementation can notice this during translation and instead of producing a program, it can advise you that you might be doing something you didn't think you were doing.

By contrast, if you read the initializer for the cp1 pointer, it intuitively suggests that it can access any byte of the foo structure, including padding.

In summary, this can produce undefined behaviour during translation (a warning or error) or during program execution (by encoding bounds information); there's no difference, standard-wise: The behaviour is undefined.


You can cast your pointer into a pointer to a pointer to array to ensure the correct array semantics.

This code is indeed not defined but provided as a C extension in every compiler in common usage today.

However the correct way of doing it would be to cast the pointer into a pointer to array as so:

((int (*)[2])p)[0][0]

to get the zeroth element or say:

((int (*)[2])p)[1][1]

to get the last.

To be strict, he reason I think this is illegal is that you are breaking strict aliasing, pointers to different types may not point to the same address (variable).

In this case you are creating a pointer to an array of ints and a pointer to an int and pointing them to the same value, this is not allowed by the standard as the only type that may alias another pointer is a char * and even this is rarely used properly.