sizeof(void()) 是一个合法的表达吗?



从[5.3.3/1],我发现:

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

从 [3.9/5] 我发现:

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

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

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

void()是一个函数类型(它是一个不带参数且不返回任何内容的函数(,因此它在sizeof()中不是有效的类型。

通过查看 CppReference.com - sizeof 运算符,文档字面意思是:

sizeof不能与函数类型、不完整类型或 位域gl值。

由于void()是函数类型,因此sizeof(void())不是法律表达式。

在他们的使用示例中,我们可以看到他们的错误注释:

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

此外,如果您编译代码,例如以下示例:

#include <iostream>
int main()
{
   std::cout << sizeof(void());
}

代码编译正确并生成值 1,但如果您查看编译,您会看到以下内容:

main.cpp:在函数 'int main((' 中:

main.cpp:5:29: 警告:对函数类型"sizeof"的应用无效 [-Wpointer-arith]

std::cout <<sizeof(void(((;

因此,很明显,sizeof()不适用于函数类型,因此代码会生成警告。它是无效的。


在这里编码

一个小前提。

这个问题源于对sizeof运营商的误解。
事实上,OP认为void() sizeof上下文中具有不完整类型的表达式,问题本身可以理解为-为什么sizeof接受表达式void(),这是一个不完整的类型,不应该接受工作草案中提到的
这就是为什么实际上提到[3.9/5]的原因,否则它就没有意义了。

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

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

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

答案如下:

  • sizeof(void()) 中的void()被解释为函数类型,并且它的格式不正确,如 [5.3.3/1](强调我的(:

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

  • sizeof((void())) 中的(void())是一个具有不完整类型 void 的表达式(请注意,sizeof 是未计算的上下文(,并且它的格式不正确,如 [5.3.3/1](强调我的(:

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

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

正如此处文档中已经强调的那样 http://en.cppreference.com/w/cpp/language/sizeof

笔记

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

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

注意:

void()是一个不带参数且不返回任何内容的函数

引用文档中的示例:

//<< "size of function: " << sizeof(void()) << 'n'  // error

所以回答你的问题:

1(不,这不是法律表达。

2(它将显示为 1 ,但将显示警告

3(同1(。

来自 C99 参考编号的 Straigth

在文档第 6.5.3.4 节 运算符的大小下说明:

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

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

  1. void 类型包含一组空值;它是无法完成的不完整类型
  2. 。函数类型描述具有指定返回类型的函数。函数类型的特征在于其返回类型及其参数的数量和类型。 函数类型被称为从其返回类型派生,如果其返回类型为 T,则函数类型有时称为"返回 T"的函数。从返回类型构造函数类型称为"函数类型派生"。

因此,void(( 是一个派生自不完整类型的函数类型,其作为 size 的操作数是非法的。也就是说,它的返回将取决于编译器实现,并且没有任何返回值保证

C99 标准

最新更新