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

sky*_*ack 50 c++ sizeof void language-lawyer

[5.3.3/1]开始,我发现:

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

[3.9/5]我发现:

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

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

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

Som*_*ude 58

void()是一个函数类型(它是一个不带参数并且不返回任何内容的函数),所以它不是一个有效的类型sizeof().

  • 那么为什么`decltype(void(void))`不起作用,以及`decltype(int(int))` 不,使用`clcltype`时它不是函数类型.在"sizeof"的情况下,我不能说. (6认同)
  • @skypjack当你使用带有`decltype`的函数类型时,它给出了返回类型的类型.在`void()`的情况下,返回类型是`void`,因此它是`decltype(void())`的类型. (5认同)
  • 是不是解释为`decltype(void())`(请注意,在这种情况下它不是函数类型)?我本来会说的.他们为什么不同? (4认同)
  • [cppreference的sizeof(http://en.cppreference.com/w/cpp/language/sizeof)提供的`sizeof` opeartor一个例子使用,并且它清楚地说**的功能尺寸**为`的sizeof(无效( )),并说,这是一个错误,这里,`// cout <<"函数的大小:"<< sizeof(void())<<'\n'; //错误`,我认为它真的是一种功能类型. (4认同)
  • @skypjack我想我现在想出来了,`decltype`需要一个*表达*,而不是一个类型.`void()`在这里实际上不是一个类型,但是一个表达式,一个C风格的转换(就像例如`int(12.34)`)`void(void)`不是表达式因此它不起作用.编译器解析不同的东西取决于上下文,当它期望一个类型它作为一个类型解析时,它需要一个表达式解析它作为一个表达式.`sizeof()`(带括号)首先需要一个类型,否则它被解析为带括号的表达式. (3认同)
  • @JoachimPileborg我会为此创建一个问题并接受这个确切的答案,以便将其留给未来的读者.你怎么看?答案确实是一个有趣的答案. (2认同)

Kha*_*laf 39

从查看CppReference.com - sizeof运算符,文档字面上指出:

sizeof不能与函数类型,不完整类型或位字段glvalues一起使用.

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

在他们的使用示例中,我们可以在此行中看到他们的错误评论:

std::cout << "size of function: " << sizeof(void()) << '\n'; // error
Run Code Online (Sandbox Code Playgroud)


Arn*_*rah 9

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

#include <iostream>

int main()
{
   std::cout << sizeof(void());
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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


代码在这里



sky*_*ack 6

一个小前提.

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

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

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

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

答案如下:

  • void()in sizeof(void())被解释为一种函数类型,并且[5.3.3/1](强调我的)是格式错误的:

    sizeof运算符不应该应用于具有函数或不完整类型的表达式,这些类型的括号名称,[...]

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

    sizeof运算符不应该应用于具有函数或不完整类型的表达式,这些类型的括号名称,[...]

在这两种情况下,GCC都会使用警告编译代码.