C++ sizeof(…;)运算符结果的混淆用法

C++ sizeof(…;)运算符结果的混淆用法,c++,c,struct,syntax,sizeof,C++,C,Struct,Syntax,Sizeof,我最近在浏览时遇到: static char zsocket_name[sizeof((struct sockaddr_un*)0)->sun_path]={}; …这令人困惑,因为在我看来,sizeof运算符的结果似乎被指针取消引用以访问名为sun\u path的结构字段,并且该值将用于调整静态存储中的数组大小 但是,当我试图计算((struct sockaddr_un*)0)->sun_path的表达式sizeof时,它会生成sockaddr_un结构的sun_path成员的大小 很明显,

我最近在浏览时遇到:

static char zsocket_name[sizeof((struct sockaddr_un*)0)->sun_path]={};
…这令人困惑,因为在我看来,
sizeof
运算符的结果似乎被指针取消引用以访问名为
sun\u path
的结构字段,并且该值将用于调整静态存储中的数组大小

但是,当我试图计算((struct sockaddr_un*)0)->sun_path的表达式
sizeof
时,它会生成
sockaddr_un
结构的
sun_path
成员的大小

很明显,这就是原文作者的意图;但是我发现它在语法上很混乱,因为它看起来像是对
sizeof(…)
操作结果的指针解引用

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

< p>在C++中,除了“代码”>“sixof(type)< />代码>之外,还有一个形式<代码>代码sisix表达式<代码>,因此:
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表达式
表单

您唯一不能做的是
size of type
,因此这是无效的

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

一种更现代的方法,在C++中获得结构域,而不将代码<代码> 0 /代码>指向指针,将使用:

std::declval().sun\u路径的大小
您的错误是认为
sizeof
的工作原理类似于函数调用,而实际上它是一个运算符根本不需要使用
()

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

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


没有
sizeof(表达式)
form
sizeof x
计算表达式
x
结果的大小(不计算
x
sizeof(x)
计算表达式
(x)
的结果大小,同样不计算它。您碰巧有一个形式为
sizeof a->b
的表达式,它(由于优先规则)与
sizeof(a->b)
等价,而不是
sizeof(a)->b
(这将触发编译错误)。

检查a。有两种形式。但是,代码应该有一个空格,因为这样会产生误导。@chris aha我想我明白了–与
sizeof(type)
相反,
sizeof表达式
表单没有括号,因此添加的任何括号都是表达式的一部分。如果您能够使用它,我建议
std::declval
,它传达了更好的含义,看起来不像一个可怕的空ptr-deref。我很惊讶没有人提到sizeof表达式在运行时不计算表达式,所以你可以编写任何语法正确的表达式,即使是一个未定义的行为,如果你想。。。这就是为什么“取消对nul指针的引用”在这里是正确的,因为这里没有真正的取消引用,只有一个具有类型但从未被计算机真正计算过的表达式。只需尝试
sizeof(实际上可能看起来是这样的)(根据cppreference.com文档)带有parens的表单用于检索类型的大小;如果没有parens,则其计算结果为表达式的大小–因此,如果您有类似于
sizeof(\u expression\ux)的内容
表达式中实际上包含了参数,因为它是没有参数的非类型形式的
sizeof
。这非常令人困惑的原因是
sizeof(…)
看起来像一个函数调用,但它不是,它是一个运算符–尽管运算符的一种形式看起来更像函数调用-y。啊哈,谢谢,在您的示例中,
decltype
在这种情况下非常清楚。请注意,
(表达式)
也是一个表达式。您可以就“您是否在表达式周围使用括号”。就我个人而言,我总是使用全括号形式,因此我会在C-
decltype
is(最多)中编写
sizeof(((struct sockaddr_un*)0)->sun_path)
C语言中的一个非标准扩展。它避免了像问题中那样令人讨厌的问题。我已经有其他人强烈否认了这个观点的有效性。辩论结束后,我们只是停留在口头上。对–事实上,它似乎是某种东西ála
sizeof(a)->b
是我最初困惑的根源;我感谢您对本例中运算符优先规则的澄清,谢谢。
sizeof std::declval<sockaddr_un>().sun_path