The result of some pointer casts are described as unspecified. For example, [expr.static.cast]/13:
A prvalue of type “pointer to cv1 void” can be converted to a prvalue of type “pointer to cv2 T,” [...] If the original pointer value represents the address A of a byte in memory and A satisfies the alignment requirement of T, then the resulting pointer value represents the same address as the original pointer value, that is, A. The result of any other such pointer conversion is unspecified.
My question is: in the case where alignment is not satisfied, what are the possible results?
For example, are the following results permitted?
- a null pointer
- an invalid pointer value (i.e. pointer which does not point to allocated storage of size
T
) - a valid pointer to a
T
in a completely separate part of memory
Code sample for reference:
#include <iostream>
int main(int argc, char **argv)
{
int *b = (int *)"Hello, world"; // (1)
*b = -1; // (2)
std::cout << argc << '\n';
}
Line (1)
triggers my above quote from [expr.static.cast]/13 because it is a reinterpret_cast
which is covered by [expr.reinterpret.cast]/7 which defines the conversion in terms of static_cast
ing through void *
.
If the unspecified result may be an invalid pointer value, then line (1)
may cause a hardware trap. (Reference: N4430 which clarifies similar wording that was in C++14 and C++11).
Corollary question: is there any case in which line 1
would cause undefined behaviour? (I don't think so at this stage; since C++14 invalid pointer value reading is implementation-defined or causes a hardware trap).
Also interesting is that line (2)
would in most cases be undefined behaviour due to strict aliasing violation (and perhaps other reasons too), however if the unspecified result may be &argc
then this program could output -1
without triggering undefined behaviour!
As far as I can tell N4303: Pointer safety and placement new partially answers this question, although somewhat indirectly. This paper refers to CWG issue 1412: Problems in specifying pointer conversions which brought about the changes to [expr.static.cast]/13 that you reference, specifically adding:
In reference to this change
N4303
says (emphasis mine):So an unspecified conversion can results in: