I was browsing some C++ code recently and I ran into the following line:
static char zsocket_name[sizeof((struct sockaddr_un*)0)->sun_path] = {};
… This is confusing, as it looks to me as if the result of the sizeof
operator is being pointer-dereferenced to access a struct field named sun_path
, and that value is to be used to size an array in static storage.
However, when I tried a simple snippet program to evaulate the expression sizeof((struct sockaddr_un*)0)->sun_path
, it yields the size of the sun_path
member of the sockaddr_un
struct.
Clearly, that is what the author of the original line was intending; but I find it syntactically confusing as it looks like a pointer dereference on the result of the sizeof(…)
operation.
What am I missing about this use of sizeof(…)
? Why does this expression evaluate this way?
In C++, the sizeof
operator has a form sizeof expression
in addition to the more common sizeof(type)
, so this:
sizeof ((struct sockaddr_un*)0)->sun_path
is equivalent to this:
sizeof(decltype(((struct sockaddr_un*)0)->sun_path))
The former, albeit without whitespace, is what's written in the code you posted.
Note that a parenthesized expression is also an expression, so sizeof ((struct sockaddr_un*)0)->sun_path
can also be written with extra parentheses: sizeof(((struct sockaddr_un*)0)->sun_path)
— even though this looks like the sizeof(type)
form, it's actually the sizeof expression
form applied to a parenthesized expression.
The only thing you can't do is sizeof type
, so this is invalid:
sizeof decltype(((struct sockaddr_un*)0)->sun_path)
A more modern way of getting at the struct's field in C++, without casting 0
to a pointer, would be to use declval
:
sizeof std::declval<sockaddr_un>().sun_path