虚空的大小是多less?
这个声明会产生什么?
void * p = (void*) malloc(sizeof(void));
编辑:这个问题的扩展。
如果sizeof(void)在GCC编译器中产生1,那么分配1字节的内存,指针p指向那个字节,p ++会递增到0x2346? 假设p是0x2345。 我在说p而不是* p。
void
types没有大小; 这将是一个编译错误。 出于同样的原因,你不能做这样的事情:
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落案例比较)。