这句话会产生什么结果?
void *p = malloc(sizeof(void));
编辑:问题的扩展。
如果sizeof(void)在GCC编译器中产生1,那么分配1个字节的内存并且指针p指向该字节并且p ++将递增到0x2346?假设p是0x2345。我说的是p而不是* p。
答案 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个字节的内存)来避免令人惊讶的行为(引用的大小写比较)。