虚空的大小是多less?

这个声明会产生什么?

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

编辑:这个问题的扩展。

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

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

 void n; 

编辑。 令我惊讶的是, 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 

如果你正在使用GCC,并且你没有使用编译器特定扩展的编译标志,那么sizeof(void)是1. GCC有一个非标准的扩展 。

一般来说, void是一个不完整的types,你不能使用sizeof来处理不完整的types。

虽然void可能适用于某种types,但它实际上并不具有价值。 因此,它在内存中没有大小。 获取void的大小没有定义。

void 指针只是一个语言结构,意思是指向无types内存的指针。

以无效的大小是一个GCC扩展 。

void没有大小。 在C和C ++中,expression式sizeof (void)都是无效的。

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

sizeof运算符不能应用于具有函数types或不完整types的expression式,也不能应用于这种types的带括号的名称,也不能应用于指定位域成员的expression式。

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

void是一个不完整的types。 这段是一个约束 ,意味着任何符合的C编译器都必须诊断它的违规行为。 (诊断消息可能是非致命的警告。)

C ++ 11标准有非常相似的措辞。 在这个问题被提出之后,两个版本都被发布了,但是规则又回到了1989年的ANSI C标准和最早的C ++标准。 实际上, sizeof可能不适用的不完整types的规则可以追溯到向语言中引入void

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

sizeof()不能应用于不完整的types。 void是不完整的types,不能完成。

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

在C ++中,我得到:

在函数'int main()'中:
第2行:错误:将“sizeof”应用于voidtypes
编译由于重大错误而终止。

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

而sizeof(void)本身也许没有意义,当你做任何指针math时,这是很重要的。

例如。

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

如果sizeof(void)被视为1,那么这将工作。 如果sizeof(void)被认为是0,那么你打到一个无限循环。

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

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

标准推荐的方法是使用char*来达到这种目的(指向字节的指针)。

使用sizeof时,C和C ++之间的另一个类似的区别是当你定义一个空的结构时,

 struct Empty { } empty; 

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

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

但是这只是通过引入另一个(空对象,即使是POD至less消耗1个字节的内存)来避免令人惊讶的行为(引用的angular落案例比较)。