sizeof(…)运算符结果的使用令人困惑

Confusing use of sizeof(…) operator results

本文关键字:运算符 结果 sizeof      更新时间:2023-10-16

我最近浏览了一些C++代码,遇到了以下行:

static char zsocket_name[sizeof((struct sockaddr_un*)0)->sun_path] = {};

…这很令人困惑,因为在我看来,sizeof运算符的结果似乎正在被指针取消引用,以访问名为sun_path的结构字段,而该值将用于调整静态存储中的数组大小。

然而,当我尝试一个简单的代码片段程序来提取表达式sizeof((struct sockaddr_un*)0)->sun_path时,它会产生sockaddr_un结构的sun_path成员的大小。

显然,这正是原作者的意图;但我发现它在语法上令人困惑,因为它看起来像是对sizeof(…)运算结果的指针取消引用。

关于sizeof(…)的使用,我缺少什么?为什么这个表达式是这样评价的?

在C++中,除了更常见的sizeof(type)之外,sizeof运算符还有一个形式sizeofexpression,因此:

sizeof ((struct sockaddr_un*)0)->sun_path

相当于:

sizeof(decltype(((struct sockaddr_un*)0)->sun_path))

前者虽然没有空格,但却是您发布的代码中所写的内容。


注意,带括号的表达式也是一个表达式,因此sizeof ((struct sockaddr_un*)0)->sun_path也可以用额外的括号写成:sizeof(((struct sockaddr_un*)0)->sun_path)——尽管这看起来像sizeof(type)形式,但它实际上是应用于带括号表达式的sizeofexpression形式。

唯一不能做的就是sizeoftype,所以这是无效

sizeof decltype(((struct sockaddr_un*)0)->sun_path)

在C++中获取结构字段的一种更现代的方法是使用declval:,而无需将0强制转换为指针

sizeof std::declval<sockaddr_un>().sun_path

您的错误是认为sizeof的工作原理类似于函数调用,而实际上它是一个运算符根本不需要使用()

sizeof实际上是形式为sizeof expression的运算符,并且不需要expression周围的()表达式中sizeof的优先级实际上等于++--(前缀形式)、一元+-!~(逻辑和非位)、(type)类型转换、&(的地址)、一元*(指针间接)和(2011年的C)_Alignof的优先级。所有这些都具有从右到左的关联性。

唯一优先级高于sizeof的运算符是++--(后缀形式)、函数调用(())、[]数组下标、访问结构成员的.->,以及(仅适用于1999年的C)复合文字(type){list}

不存在sizeof(expression)形式。sizeof x计算表达式x的结果大小(不计算x)。sizeof (x)计算表达式(x)的结果大小,同样不计算。您碰巧有一个形式为sizeof a->b的表达式,它(由于优先级规则)等效于sizeof (a->b),而不是sizeof(a)->b(这会引发编译错误)。