Re: Valid C++?
Alf P. Steinbach wrote:
* Tom Widmer:
Alf P. Steinbach wrote:
* Jack Klein:
Yes, dereferencing a null pointer is undefined behavior. However
since the C++ standard (like the C standard) states:
"The sizeof operator yields the number of bytes in the object
representation of its operand. The operand is either an expression,
which is not evaluated, or a parenthesized typeid."
Since the expression is itself is not evaluated, the pointer is never
dereferenced, and the behavior is completely defined.
Nope.
Dereferenced doesn't mean "at run time".
It does mean the dereference actually has to happen. sizeof
expressions are never evaluated.
Compile time constant expressions are evaluated
The expression the sizeof operator is acting on (((foo *)0)->x) is not a
constant expression (5.19). Such expressions cannot access values, as
the above one does.
, and examples have been
given in this thread where that yields different results (and UB)
depending on the expression.
So the "never" is incorrect.
Something that is 'not evaluated' is certainly never evaluated. I agree
that constant expressions do potentially need to be evaluated as part of
a sizeof in order to determine the type specified in the sizeof. e.g.
sizeof(std::bitset<4000/2>);
4000/2 has to be evaluated. But I think constant expressions are the
special case.
Hence, the argument is invalid.
>
does the following code have UB?
if (false)
{
*static_cast<int*>(0) = 10;
}
Formally it has Undefined Behavior in the same way as
if( false )
{
5/0;
}
The compiler is free to produce /any/ code for the expression "5/0",
including treating it as requiring a 3 GiB helper object and allocate
that much space on the stack on entry to the function.
The two examples are not quite equivalent, since '5/0' is an integral
constant expression (maybe an ill-formed one?), though since it isn't
used where an integral constant expression is required, I'm not entirely
sure whether it should be evaluated as such (and in fact, I don't think
it matters). I think 1.9/5 makes it clear that it must be possible for
the operation to be part of a permissible execution sequence before the
program actually has UB.
AFAICS there are only two ways out if you want the first to not be UB:
you can pinpoint where the standard differentiates pointer expressions
and integer expressions wrt. UB, so that they behave differently, or you
can pinpoint where the standard allows the second to not be formally UB.
1.9/5 is my best shot, and I think it allows both examples.
Tom