简体   繁体   中英

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?

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

Your mistake is thinking that sizeof works like a function call, whereas it is actually an operator. There is no requirement to use () at all.

sizeof is actually an operator of the form sizeof expression and the () around expression are not required. The precedence of sizeof in expressions is actually equal to that of ++ and -- (prefix form), unary + and - , ! and ~ (logical and bitwise not), the (type) typecast, & (address of), unary * (pointer indirection), and (C from 2011) _Alignof . All of these have right-to-left associativity.

The only operators with higher precedence than sizeof are ++ and -- (suffix form), function call ( () ), [] array subscripting, . and -> to access struct members, and (for C only from 1999) compound literals (type){list} .

There is no sizeof(expression) form. sizeof x evaluates the size of the result of an expression x (without evaluating x ). sizeof (x) evaluates the size of result of the expression (x) , again without evaluating it. You happen to have an expression of the form sizeof a->b which (due to precedence rules) is equivalent to sizeof (a->b) and not to sizeof(a)->b (which would trigger a compilation error).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM