Old said:
Tomás said:
int main()
{
double array[4];
array + 7;
}
This is definitely UB, see 5.6#5:
When an expression that has integral type is added to or
subtracted from a pointer
[...]
If both the pointer operand and the result point to elements of
the same array object, or one past the last element of the
array object, the evaluation shall not produce an overflow;
otherwise, the behavior is undefined.
Very true.
Actually, the WG21 intended to allow implementations having bound
checkings. Knowing that they can overflow when a pointer which points
out of the "array" is formed by addition, except in the very special
case of pointers one past the last element. It means that if you add 1
to a pointer one past the last element of an array, it may throw an
implementation specific exception.
Kai-Uwe Bux said:
No. The behavior is not undefined but implementation defined:
[5.2.10/5] (expr.reinterpret.cast)
A value of integral type or enumeration type can be explicitly converted to
a pointer. A pointer converted to an integer of sufficient size (if any
such exists on the implementation) and back to the same pointer type will
have its original value; mappings between pointers and integers are
otherwise implementation-defined.
That's true.
In particular, it means that, if you have no access to the compiler
doc, or if you want to write perfectly portable code, you can't assume
anything on the behavior.
From a standard point-of-view the behavior is undefined... But the
behavior may be well-defined (or undefined) depending on the compiler's
documentation about this pointer mapping.
An implementation is free to say something like:
Converting integers whose alignment is not correct to pointers is
undefined.
Converting integers whose alignment is correct to pointers will yield
pointers whose representation bytes are exactly the same than these of
the integers, as described in another section of this doc.
Or, even:
If the integer which is not a multiple of the required alignment of a
type is reinterpret_casted to type*, the program will throw a bad_cast
exception
Furthermore, a "safe" implementation of C++ is possible (you know,
there are even C++ interpreters). In that implementation, the compiler
may save extra data about the type of objects, and keep track of the
fact that such integer actually contains a pointer-to-something... And
in that case, the implementation may simply say:
reinterpret_casting an integer to a pointer is forbidden, except if
this integer had been computed by a reinterpret_cast operation from a
pointer type.
You may say that it is illegal since two integer types might be equal
(as tested by operator==), but the reinterpret_cast would not behave
the same...
But it's legal, because there can be several representations of the
same integer (i.e. integers can have different bytes, and still be
equal).
For instance, it allows 1's complement integers.
Thus, this integer would contain... not 1 bit, but several bytes of
extra data which would not really participate to the actual
representation.
Note that it doesn't apply to char or unsigned char.
Jim said:
I truely believe that UB only happens if you try to dereference the
behavior. I think a better question is: is this well defined behavior:
int main()
{
int SomeInt = 7;
int* p = SomeInt;
p += 100;
p -= 100;
std::cout << *p << std::endl;
}
Is that guaranteed to display 7? I would think yes.
Of course not... Do you even know that signed integer overflow is UB.
For instance:
signed char c=127;
++c; // undefined behavior (assuming that MAX_CHAR is 127).
Similarly, pointers may have such problems (i.e. overflow in operations
that would do weird undefined things).