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(表达式)
formsizeof 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语言中的一个非标准扩展。它避免了像问题中那样令人讨厌的问题。我已经有其他人强烈否认了这个观点的有效性。辩论结束后,我们只是停留在口头上。对–事实上,它似乎是某种东西álasizeof(a)->b
是我最初困惑的根源;我感谢您对本例中运算符优先规则的澄清,谢谢。
sizeof std::declval<sockaddr_un>().sun_path