我最近在浏览some C++ code并遇到了the following line:
static char zsocket_name[sizeof((struct sockaddr_un*)0)->sun_path] = {};
...这很令人困惑,因为它看起来好像sizeof
运算符的结果被指针取消引用来访问名为sun_path
的结构字段,并且该值将用于在静态存储中调整数组大小。
但是,当我尝试a simple snippet program来评估表达式sizeof((struct sockaddr_un*)0)->sun_path
时,它会产生sun_path
结构的sockaddr_un
成员的大小。
显然,这就是原作者的意图;但我发现它在语法上令人困惑,因为它看起来像是sizeof(…)
操作结果的指针取消引用。
我对sizeof(…)
的使用缺少什么?为什么这个表达式会这样评估?
答案 0 :(得分:4)
在C ++中,除了更常见的sizeof expression
外,sizeof
operator的格式为sizeof(type)
,因此:
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)
形式,它也可以使用sizeof expression
形式。实际上是sizeof type
形式应用于带括号的表达式。
sizeof decltype(((struct sockaddr_un*)0)->sun_path)
使用declval
来使用{{3}}时,更加现代的方法是在C ++中使用结构字段,而不是将0
强制转换为指针。
sizeof std::declval<sockaddr_un>().sun_path
答案 1 :(得分:4)
你的错误是认为sizeof
就像一个函数调用,而它实际上是一个运算符。 根本不需要使用()
。
sizeof
实际上是sizeof expression
表单的运算符,()
周围expression
不是必需的。 {{1}的优先级表达式实际上等于sizeof
和++
(前缀形式),一元--
和+
,-
和!
的表达式(逻辑和按位不是),~
类型转换,(type)
(地址),一元&
(指针间接)和(2011年的C)*
。所有这些都具有从右到左的相关性。
优先级高于_Alignof
的唯一运算符为sizeof
和++
(后缀形式),函数调用(--
),()
数组下标, []
和.
访问struct成员,(仅限1999年的C)复合文字->
。
没有(type){list}
表格。 sizeof(expression)
评估表达式sizeof x
的结果大小(不评估x
)。 x
再次评估表达式sizeof (x)
的结果大小,而不进行评估。您碰巧有一个(x)
形式的表达式(由于优先级规则)等同于sizeof a->b
而不是sizeof (a->b)
(这将触发编译错误)。