此语句将产生什么?
void *p = malloc(sizeof(void));
编辑:问题的扩展名。
如果sizeof(void)在GCC编译器中产生1,则分配1字节的内存,并且指针p指向该字节,并且p ++会增加到0x2346吗?假设p为0x2345。我说的是p,而不是* p。
类型void
没有大小;那将是一个编译错误。出于同样的原因,您不能执行以下操作:
void n;
编辑。令我惊讶的是,在sizeof(void)
中实际上does在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
[大多数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个字节的内存)来避免令人惊讶的行为(对引用进行角落比较)。
[如果您使用的是GCC,并且没有使用删除特定于编译器的扩展名的编译标志,则sizeof(void)
为1。GCC具有执行该操作的nonstandard extension。
通常,void
是不完整的类型,不能将sizeof用于不完整的类型。
尽管void
可能代表一种类型,但实际上不能保存值。因此,它在内存中没有大小。未定义获取void
的大小。
Avoid
pointer只是一种语言构造,表示指向untyped内存的指针。
void
没有大小。在C和C ++中,表达式sizeof (void)
都是无效的。
在C中,引用N1570 6.5.3.4第1段:
sizeof
运算符不得应用于以下表达式函数类型为或不完整的类型,括号类型为这样的类型,或者指定位域成员的表达式。
((N1570是2011 ISO C标准的草案。)
void
是不完整的类型。本段是constraint,表示任何符合标准的C编译器都必须诊断出任何对此的违反。 (诊断消息可能是非致命警告。)
C ++ 11标准的措辞非常相似。在问了这个问题之后,两个版本都发布了,但是规则可以追溯到1989年的ANSI C标准和最早的C ++标准。实际上,void
是不适用sizeof
的不完整类型的规则可以追溯到将void
引入语言的程度。
gcc具有extension,它将sizeof (void)
视为1。默认情况下,gcc不是兼容的C编译器,因此在其默认模式下,它不会警告sizeof (void)
。即使完全兼容的C编译器也可以使用这种扩展,但是仍然需要诊断。
以空隙的大小为GCC extension。
sizeof()
无法应用于不完整的类型。并且void
是无法完成的不完整类型。
在C中,在GCC中为sizeof(void) == 1
,但这似乎取决于您的编译器。
在C ++中,我得到:
在函数'int main()'中:第2行:错误:将'sizeof'无效应用到void类型由于-Wfatal-errors,编译终止。
问题的第二部分:请注意,sizeof(void *)!= sizeof(void)。在32位的arch上,sizeof(void *)是4个字节,因此将相应地设置p ++。指针的增加量取决于它所指向的数据。因此,它将增加1个字节。
虽然sizeof(void)本身没有任何意义,但是在进行任何指针数学运算时,这一点很重要。
例如
void *p;
while(...)
p++;
如果将sizeof(void)视为1,那么它将起作用。如果将sizeof(void)视为0,那么您会遇到无限循环。