C++ sizeof(void())是合法表达式吗?

C++ sizeof(void())是合法表达式吗?,c++,language-lawyer,sizeof,void,C++,Language Lawyer,Sizeof,Void,从中,我发现: sizeof运算符不得应用于具有函数或不完整类型的表达式 从中我发现: 定义不完整的对象类型和cv void是不完整的类型 无论如何,因为sizeof不计算它的操作数,我会说sizeof(void())是一个合法的表达式(实际上是GCC编译的,结果是1)。 另一方面,在讨论sizeof时,从中没有提到void,也没有提到大小为1的类型,也没有提到具有实现定义大小的类型列表 因此问题是:sizeof(void()) 是否保证大小等于1? 或者这是一个导致UB的法律表达,仅此而已?从

从中,我发现:

sizeof运算符不得应用于具有函数或不完整类型的表达式

从中我发现:

定义不完整的对象类型和cv void是不完整的类型

无论如何,因为
sizeof
不计算它的操作数,我会说
sizeof(void())
是一个合法的表达式(实际上是GCC编译的,结果是1)。
另一方面,在讨论
sizeof
时,从中没有提到
void
,也没有提到大小为1的类型,也没有提到具有实现定义大小的类型列表

因此问题是:
sizeof(void())
是否保证大小等于1?
或者这是一个导致UB的法律表达,仅此而已?

从字面上看,文档说明:

sizeof
不能与函数类型、不完整类型或 位字段值

既然
void()
是函数类型,那么
sizeof(void())
就不是合法的表达式

在他们的用法示例中,我们可以在这一行看到他们的错误注释:

std::cout << "size of function: " << sizeof(void()) << '\n'; // error

std::cout
void()
是一个函数类型(它是一个不带参数且不返回任何内容的函数),因此如果编译代码,它在
sizeof()

中也不是有效的类型,例如下面的示例:

#include <iostream>

int main()
{
   std::cout << sizeof(void());
}
#包括
int main()
{

std::cout已在此处的文档中突出显示

注释

sizeof()
不能与函数类型、不完整类型或位字段值一起使用

由于
void()
是函数类型,因此它不是有效的
sizeof()

注:

void()

引用文档中的一个示例:

//<< "size of function: " << sizeof(void()) << '\n'  // error
/一个小前提

这个问题源于对
sizeof
运算符的误解。
事实上,OP认为
void()
是一个在
sizeof
上下文中类型不完整的表达式,问题本身可以理解为-why
sizeof
接受表达式
void()
,这是一个不完整的类型,不应该像工作草案中提到的那样被接受?
这就是为什么会提到[3.9/5],否则就没有意义了

也就是说,事实上这个问题实际上包含两个有趣的问题:

  • 为什么
    sizeof(void())
    不合法?
    这是从标题本身来看的实际问题

  • 为什么
    sizeof((void())
    不合法?
    这是OP的预期问题

答复如下:

  • sizeof(void())
    中的
    void()
    被解释为函数类型,它的格式与(emphasis mine)相同:

    sizeof运算符不得应用于具有函数类型或不完整类型的表达式,也不得应用于此类类型的括号名称
    ,[…]

  • sizeof((void())
    中的
    (void())
    是一个类型不完整的表达式
    void
    (请注意,
    sizeof
    是一个未计算的上下文),它的格式与(我的强调部分)相同:

    sizeof运算符不得应用于具有函数或不完整类型的表达式,也不得应用于此类类型的括号名称[…]


在这两种情况下,GCC都会编译带有警告的代码。

从C99参考号开始

第6.5.3.4节下的文件中规定了运营商的规模:

sizeof运算符不得应用于具有函数类型或不完整类型的表达式、此类类型的括号名称或指定位字段成员的表达式

根据第6.2.5节第19项和第20项,类型:

  • void类型包含一组空值;它是一个不完整的类型,无法完成
  • …函数类型描述具有指定返回类型的函数。函数类型以其返回类型及其参数的数量和类型为特征。 函数类型称为从其返回类型派生,如果其返回类型为T,则函数类型有时称为“函数返回T”。从返回类型构造函数类型称为“函数类型派生”
  • 因此,void()是从不完整类型派生的函数类型,它作为sizeof的操作数是非法的。也就是说,它的返回将取决于编译器实现,并且不保证有任何返回值


    说这是一个错误GCC过去有(可能现在仍然有)扩展,其中
    sizeof(void)==1
    我的g++副本说:
    警告:“sizeof”对函数类型的应用无效[-Wpointer arith]
    应用程序可能会抑制错误/警告messages@skypjack答案是相同的-因此不是。它不是在
    decltype(void())
    中解释的(注意,在这种情况下它不是函数类型)?我真的会这么说。为什么它们不同?@skypjack当你使用带有
    decltype
    的函数类型时,它给出了返回类型的类型。在
    void()
    的情况下,返回类型是
    void
    所以这就是
    decltype(void())
    的类型。那么为什么
    decltype(void(void))呢
    不起作用,以及
    decltype(int(int))
    ?不,使用
    decltype
    时,它不是函数类型。在
    sizeof
    的情况下,我不能说。@skypjack我想我现在明白了,
    decltype
    需要一个表达式,而不是一个类型。
    void()
    在这里实际上不是一种类型,而是一种表达式,一种C样式转换(j