Re: Valid C++?
On Tue, 06 Jun 2006 21:41:07 +0200, "Alf P. Steinbach"
<alfps@start.no> wrote in comp.lang.c++:
* Rolf Magnus:
Alf P. Steinbach wrote:
* Victor Bazarov:
andrew queisser wrote:
Is this code below valid C++? I'd like to use this construct but I'm
not sure if it'll be portable.
struct foo
{
char x[128];
};
struct bar
{
char sameSizeAsFooX[ sizeof ((foo *)0)->x ];
It is OK, I guess. Seems rather dangerous though, like dereferencing
a null pointer. Perhaps it would be less scary to do
char sameSizeAsFoox[ sizeof foo().x ];
(although it does require for 'foo' to be default-constructible while
your solution does not).
};
On the one hand, dereferencing a null-pointer is formally UB no matter
which context (except in a typeid expression).
Actually, the exception covers not only typeid, but also sizeof:
"An expression is potentially evaluated unless either it is the operand of
the sizeof operator (5.3.3), or it is the operand of the typeid operator
and does not designate an lvalue of polymorphic class type (5.2.8)."
No, that isn't the exception that applies to typeid.
And no, it doesn't matter whether a dereferencing is potentially
evaluated or not.
The statement above makes no sense. I have no idea what "potentially
evaluated" means.
Consider:
int main()
{
int x = 0;
int *ip = 0;
if (x)
{
x = *ip;
}
return x;
}
This program has completely defined behavior, and in fact main() will
return 0. The program contains an expression that would cause UB,
namely dereferencing a null pointer. But dereferencing a null (or
otherwise invalid) pointer can only cause UB if it is actually
executed at run time. That cannot happen in the sample as written,
because the expression is never evaluated.
The standard guarantees that if the operand of sizeof operator is an
expression, that expression is not evaluated. The expression is only
parsed, at compile time, to determine the type of the expression.
Since it may only be applied to complete types, the compiler knows the
size of the object representation from the type. The pointer is not
dereferenced, and in fact does not actually exist at compile time.
All of these are perfectly legal and defined:
sizeof 1/0; // yields sizeof(int)
sizeof 100.0/0 // yields sizeof(double)
....and given:
struct z { int x; double y );
struct z *zp = 0;
....then:
sizeof zp->y; // yields sizeof(double)
....is likewise perfectly legal, and so is:
sizeof (z*)0->y;
The actual temporary pointer is never formed, let along dereferenced.
--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.contrib.andrew.cmu.edu/~ajo/docs/FAQ-acllc.html