能否存在一个占用0字节的c++类型?

Can there be a C++ type that takes 0 bytes

本文关键字:字节 c++ 类型 一个 存在      更新时间:2023-10-16

我试图声明一个占用零字节的c++变量。它在一个联合中,我开始的类型是int[0]。我不知道这是否真的是零字节(尽管sizeof(int[0])是0)。我需要一个更好的方法来声明一个0字节类型,希望可以被类型定义为像nullType或emptyType这样的东西。变量是在一个联合中,所以在最后内存是保留的。我尝试了void,希望它能工作,但是c++抱怨了。我使用的是Ubuntu 10.10,带有当前版本的内核和最新的GCC。这里是联合:

union RandomArgumentTypesFirst
{
    uint uintVal;
    nullType nullVal;
}
这里是typepedef:
typedef int[0] nullType;

编译器对typedef这样说:

error: variable or field ‘nullVal’ declared voidmake[2]:

当我输入int[0]时,它工作了。有什么建议吗?

编辑:正如@fefe在评论中所说,int[0]可能由编译器作为扩展提供。GCC的网站说编译器默认有很多扩展。

typepedef拼写错误:

typedef int nullType[0];

正如其他人指出的,你不能有一个大小为0的对象;然而,编译器可以(并且经常)提供 Empty Base Class 优化。

  • http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Empty_Base_Optimization
  • http://www.cantrip.org/emptyopt.html("空成员"优化)

在c++中不能实例化任何占用零字节的数据类型。标准规定了一个空类,例如:

class Empty {};

…将导致以下为真:

Empty emp;
assert( sizeof(emp) != 0 );

这样做的原因是您可以获取对象的地址。

编辑:我最初说sizeof将是1,但根据@ al的评论,我在标准中找到了相关的段落,它确实只是非零:

(类)§9/3

类类型的完整对象和成员子对象必须具有非零大小

标准明确禁止存在大小为0的类型实例,原因是如果一个对象的大小可以为0,那么两个不同的对象可以位于完全相同的地址。例如,一个空结构体,即使用作不同类型的基,编译器也可以让它的size == 0,它也必须具有size> 0的值以符合这一要求。

你想用空类做什么?

c++中的变量永远不能为零字节。每个对象必须有唯一的地址,如果大小为0,这是不可能的。

顺便说一下,int[0]在标准c++中是非法的。如果您使用的是GCC,使用-pedantic选项编译它,您将得到以下警告:
warning: ISO C++ forbids zero-size array 'x' [-pedantic]

同样,typedef的语法应该是这样的:

  typedef int array[100]; //zero cannot be size - illegal!

c++标准明确要求每个类型的size至少为1。这与每个对象都有唯一地址的要求密切相关(如果Foo的大小为0,则考虑Foo x[10])。

听起来你想要std::optional.
它不会有sizeof 0,但这对于表达空值并不重要。


在一个相关的注意,有一个c++提案(P0146R1)使void成为一个常规类型。
论文继续讨论了为什么sizeof(void)不能为0。

为什么sizeof(void)不等于0?

一个反复出现的建议是设置sizeof(void)报告0并允许多个实例共享相同的地址。这将防止用户不得不使用类似于空的技巧基础优化,以便更优化地使用内存。理想情况下,这将是这种情况,但这种语言的变化既庞大又超出了提案的范围。允许类型具有的大小为0,并且允许不同的实例共享一个地址,这意味着对现有代码进行剧烈而微妙的破坏性更改。例如,如果你要创建这样一个void类型的数组,一个指针,至少在传统意义上的,将不再能够作为一种迭代器放入该数组(特别意味着泛型代码依赖于这种0大小的类型现在会失败)。同样,任何依赖于对象的类型和地址作为惟一的代码将会失败对于void类型,即使它在其他方面完全可以接受。最后,如果void允许这样的大小,那么它确实应该允许允许用于任何类型,包括用户定义的类型。吃特价菜无效规则会让你多考虑一件事对void类型的处理方式不同。相反,这个提案选择了不指定void的大小,因此由existing控制语言规则。在实践中,预计可能会出现空白在大多数实现中大小为1,尽管这不是必需的。如果一个最终对语言进行了修改,允许大小为0的类型,那么void就可以隐式地利用这一点。

虽然这个问题是针对c++的,但应该注意的是,C中的空结构可能导致sizeof为0。然而,这是未定义的行为。

如果struct-declaration-list不包含命名成员,则是未定义的。