Search code examples
c++cstructsyntaxsizeof

Confusing use of sizeof(…) operator results


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?


Solution

  • 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