Reputation: 35408
I came over the following code construct in our production environment (heavily simplified however).
#include <iostream>
typedef struct
{
char entry[10];
}
inn_struct;
typedef struct
{
inn_struct directory;
}
out_struct;
struct test
{
static const int
ENTRY_LENGTH = (sizeof((static_cast<out_struct*>(0))->directory.entry)
/ sizeof((static_cast<out_struct*>(0))->directory.entry[0]));
};
int main()
{
test a;
std::cout << test::ENTRY_LENGTH;
}
Now not considering the obviously obfuscated nature of it since it's just the old C way of determining the length of an array ... I am really bothered by the static_cast
of the 0
value. ... Is this code acceptable? Can you please attach some passages from the c++ standard to your response which tells me (if) why this code is ok?
Upvotes: 1
Views: 75
Reputation: 303087
Yes, this code is perfectly acceptable. See §5.3.3/1 (emphasis mine).
The sizeof operator yields the number of bytes in the object representation of its operand. The operand is either an expression, which is an unevaluated operand (Clause 5), or a paranthesized type-id.
The expression is not evaluated, so there's no problem with what looks like dereferencing a null pointer.
Note also that in C++11, you don't need to jump through that hoop, and can just directly reference the class member with sizeof, thanks to §5/8 (emphasis mine):
In some contexts, unevaluated operands appear (5.2.8, 5.3.3, 5.3.7, 7.1.6.2). An unevaluated operand is not evaluated. An unevaluated operand is considered a full-expression. [ Note: In an unevaluated operand, a non-static class member may be named (5.1) and naming of objects or functions does not, by itself, require that a definition be provided (3.2). — end note ]
and §5.1.1/13:
An id-expression that denotes a non-static data member or non-static member function of a class can only be used:
..
if that id-expression denotes a non-static data member and it appears in an unevaluated context [Example:
struct S {
int m;
};
int i = sizeof(S::m); // OK
int j = sizeof(S::m + 42); // OK
- end example]
Upvotes: 4