虚空的大小是多少?

时间:2009-11-03 09:30:11

标签: c++ c

这句话会产生什么结果?

void *p = malloc(sizeof(void));

编辑:问题的扩展。

如果sizeof(void)在GCC编译器中产生1,那么分配1个字节的内存并且指针p指向该字节并且p ++将递增到0x2346?假设p是0x2345。我说的是p而不是* p。

10 个答案:

答案 0 :(得分:46)

void类型没有大小;这将是一个编译错误。出于同样的原因,你不能做类似的事情:

void n;

EDIT。 令我惊讶的是,sizeof(void)实际 在GNU C中进行编译:

$ echo 'int main() { printf("%d", sizeof(void)); }' | gcc -xc -w - && ./a.out 
1

然而,在C ++中却没有:

$ echo 'int main() { printf("%d", sizeof(void)); }' | gcc -xc++ -w - && ./a.out 
<stdin>: In function 'int main()':
<stdin>:1: error: invalid application of 'sizeof' to a void type
<stdin>:1: error: 'printf' was not declared in this scope

答案 1 :(得分:38)

如果您正在使用GCC而您没有使用删除编译器特定扩展的编译标志,则sizeof(void)为1. GCC有nonstandard extension即可。

通常,void是不完整的类型,您不能将sizeof用于不完整的类型。

答案 2 :(得分:15)

虽然void可能适用于某个类型,但它实际上不能保存值。因此,它在内存中没有大小。没有定义void的大小。

void 指针只是一种语言构造,意味着指向无类型内存的指针。

答案 3 :(得分:10)

取无效的大小为GCC extension

答案 4 :(得分:10)

void没有尺寸。在C和C ++中,表达式sizeof (void)无效。

在C中,引用N1570 6.5.3.4第1段:

  

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

(N1570是2011 ISO C标准的草案。)

void是一种不完整的类型。此段落是约束,这意味着任何符合要求的C编译器必须诊断任何违反它的行为。 (诊断消息可能是非致命警告。)

C ++ 11标准的措辞非常相似。这两个版本都是在提出这个问题后发布的,但规则可以追溯到1989年ANSI C标准和最早的C ++标准。事实上,void是一个不适用sizeof的不完整类型的规则可以追溯到将void引入语言的过程。

gcc有一个扩展名,它将sizeof (void)视为1.默认情况下,gcc不是一个符合标准的C编译器,所以在默认模式下它不会警告sizeof (void) 。即使对于完全符合C的编译器,也允许这样的扩展,但仍然需要诊断。

答案 5 :(得分:5)

sizeof()无法应用于不完整类型。 void是不完整的类型,无法完成。

答案 6 :(得分:3)

在C中,GCC中为sizeof(void) == 1,但这似乎取决于您的编译器。

在C ++中,我得到:

In function 'int main()':
Line 2: error: invalid application of 'sizeof' to a void type
compilation terminated due to -Wfatal-errors.

答案 7 :(得分:0)

问题的第二部分:注意sizeof(void *)!= sizeof(void)。  在32位arch上,sizeof(void *)是4个字节,因此p ++将相应地设置。指针递增的数量取决于它指向的数据。因此,它将增加1个字节。

答案 8 :(得分:-1)

虽然sizeof(void)本身可能没有任何意义,但是当你进行任何指针数学时这很重要。

例如

 void *p;
 while(...)
      p++;

如果sizeof(void)被认为是1那么这将起作用。 如果sizeof(void)被认为是0,那么你会遇到无限循环。

答案 9 :(得分:-1)

大多数C ++编译器在尝试获取sizeof(void)时选择引发编译错误。

编译C时,gcc不符合并选择将sizeof(void)定义为1.它可能看起来很奇怪,但有一个基本原理。当您执行指针运算时,添加或删除一个单位意味着添加或删除指向大小的对象。因此,将sizeof(void)定义为1有助于将void*定义为指向字节的指针(无类型内存地址)。否则,使用像p+1 == p when p void*这样的指针算法会产生令人惊讶的行为。在c ++中不允许对void指针进行这样的指针运算,但在使用gcc编译C时可以正常工作。

标准推荐方法是将char*用于此类目的(指向字节的指针)。

使用sizeof时,C和C ++之间的另一个类似差异发生在定义空结构时:

struct Empty {
} empty;

使用gcc作为我的C编译器sizeof(empty)返回0。 使用g ++,相同的代码将返回1。

我不确定C和C ++标准在这一点上是什么,但我相信定义一些空结构/对象的大小有助于参考管理以避免两个引用不同的连续对象,第一个空着,得到相同的地址。如果通常使用隐藏指针实现引用,则确保使用不同的地址将有助于比较它们。

但这只是通过引入另一个(空对象,甚至POD消耗至少1个字节的内存)来避免令人惊讶的行为(引用的大小写比较)。