混淆使用 sizeof(…) 运算符结果
Confusing use of sizeof(…) operator results
我正在浏览 some C++ code recently and I ran into 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
时,它会产生 sockaddr_un
结构的 sun_path
成员的大小。
很明显,这就是原文作者的意图;但我发现它在语法上令人困惑,因为它看起来像是对 sizeof(…)
操作结果的指针取消引用。
关于 sizeof(…)
的这种用法,我遗漏了什么?为什么这个表达式会这样计算?
在 C++ 中,sizeof
operator 除了更常见的 之外,还有一种形式 <code>sizeof <em>expression</em>
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(<em>type</em>)
形式,实际上是sizeof <em>expression</em>
形式应用于括号表达式。
你唯一不能做的就是sizeof <em>type</em>
,所以这是无效:
sizeof decltype(((struct sockaddr_un*)0)->sun_path)
在不将 0
强制转换为指针的情况下,在 C++ 中获取结构字段的一种更现代的方法是使用 declval
:
sizeof std::declval<sockaddr_un>().sun_path
你的错误是认为 sizeof
像函数调用一样工作,而实际上它是一个运算符。 根本不需要使用()
。
sizeof
实际上是sizeof expression
形式的运算符,不需要expression
周围的()
。 sizeof
在表达式中的优先级实际上等于++
和--
(前缀形式)、一元+
和-
、!
和~
(逻辑和按位非),(type)
类型转换,&
(地址),一元 *
(指针间接),以及(2011 年的 C)_Alignof
.所有这些都具有 right-to-left 关联性。
唯一比sizeof
优先级高的运算符是++
和--
(后缀形式)、函数调用(()
)、[]
数组下标,.
和 ->
以访问结构成员,以及(仅适用于 1999 年的 C)复合文字 (type){list}
.
没有sizeof(expression)
表格。 sizeof x
计算表达式 x
的结果大小(不计算 x
)。 sizeof (x)
计算表达式 (x)
结果的大小,再次不计算它。您碰巧有一个 sizeof a->b
形式的表达式,它(由于优先规则)等效于 sizeof (a->b)
而不是 sizeof(a)->b
(这会触发编译错误)。
我正在浏览 some C++ code recently and I ran into 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
时,它会产生 sockaddr_un
结构的 sun_path
成员的大小。
很明显,这就是原文作者的意图;但我发现它在语法上令人困惑,因为它看起来像是对 sizeof(…)
操作结果的指针取消引用。
关于 sizeof(…)
的这种用法,我遗漏了什么?为什么这个表达式会这样计算?
在 C++ 中,sizeof
operator 除了更常见的 之外,还有一种形式 <code>sizeof <em>expression</em>
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(<em>type</em>)
形式,实际上是sizeof <em>expression</em>
形式应用于括号表达式。
你唯一不能做的就是sizeof <em>type</em>
,所以这是无效:
sizeof decltype(((struct sockaddr_un*)0)->sun_path)
在不将 0
强制转换为指针的情况下,在 C++ 中获取结构字段的一种更现代的方法是使用 declval
:
sizeof std::declval<sockaddr_un>().sun_path
你的错误是认为 sizeof
像函数调用一样工作,而实际上它是一个运算符。 根本不需要使用()
。
sizeof
实际上是sizeof expression
形式的运算符,不需要expression
周围的()
。 sizeof
在表达式中的优先级实际上等于++
和--
(前缀形式)、一元+
和-
、!
和~
(逻辑和按位非),(type)
类型转换,&
(地址),一元 *
(指针间接),以及(2011 年的 C)_Alignof
.所有这些都具有 right-to-left 关联性。
唯一比sizeof
优先级高的运算符是++
和--
(后缀形式)、函数调用(()
)、[]
数组下标,.
和 ->
以访问结构成员,以及(仅适用于 1999 年的 C)复合文字 (type){list}
.
没有sizeof(expression)
表格。 sizeof x
计算表达式 x
的结果大小(不计算 x
)。 sizeof (x)
计算表达式 (x)
结果的大小,再次不计算它。您碰巧有一个 sizeof a->b
形式的表达式,它(由于优先规则)等效于 sizeof (a->b)
而不是 sizeof(a)->b
(这会触发编译错误)。