The Standard does not require that compilers behave predictably if an object of type "int" is accessed using an lvalue that has no visible relation to that type. In the rationale, however, the authors note that the classification of certain actions as Undefined Behavior is intended to allow the marketplace to decide what behaviors are considered necessary in quality implementations. In general, the act of converting a pointer to another type and then immediately performing an access with it falls in the category of actions which will be supported by quality compilers that are configured to be suitable for system programming, but may not be supported by compilers that act obtusely.
Even ignoring the lvalue-type issue, however, the Standard imposes no requirements as to what happens if an application tries to read from memory it does not own. Here again, the choice of behavior may sometimes be a quality-of-implementation issue. There are five main possibilities here:
On some implementations, the contents of the storage might be
predictable via means not described by the Standard, and the read
would yield the contents of such storage.
The act of reading might behave as though it yields bits with
Unspecified values, but have no other side-effect.
The attempted read may terminate the program.
On platforms which use memory-mapped I/O, the out-of-bounds read could
perform an unexpected operation with unknown consequences; this
possibility is only applicable on certain platforms.
Implementations that try to be "clever" in various ways may try to
draw inferences based on the notion that the read cannot occur, thus
resulting in side-effects that transcend laws of time and causality.
If you know that your code will be running on a platform where reads have
no side-effects, the implementation won't try to be "clever", and your code
is prepared for any pattern of bits the read might yield, then under those
circumstances such a read may have useful behavior, but you would be limiting
the situations where your code could be used.
Note that while implementations that define __STDC_ANALYZABLE__
are required
to have most actions obey the laws of time and causality even in cases where
the Standard would impose no other requirements, out-of-bounds reads are
classified as Critical Undefined Behavior, and should thus be considered
dangerous on any implementation that does not expressly specify otherwise.
Incidentally, there's another issue on some platforms which would apply even if e.g. code had used an int[3]
rather than a single int
: alignment. On some platforms, values of certain types may only be read or written to/from certain addresses, and some addresses which are suitable for smaller types may not be suitable for larger ones. On platforms where int
requires 32-bit alignment but double
requires 64-bit alignment, given int foo[3]
, a compiler might arbitrarily place foo
so that (double*)foo
would be a suitable address for storing a double
, or so that (double*)(foo+1)
would be a suitable place. A programmer who is familiar with the details of an implementation may be able to determine which address would be valid and exploit that, but code which blindly assumes that the address of foo
will be valid may fail if double
has a 64-bit alignment requirement.