这个陈述会产生什么?
void *p = malloc(sizeof(void));
编辑:问题的扩展。
如果 sizeof(void) 在 GCC 编译器中产生 1,则分配 1 个字节的内存并且指针 p 指向该字节并且 p++ 会递增到 0x2346?假设 p 是 0x2345。我说的是 p 而不是 *p。
这个陈述会产生什么?
void *p = malloc(sizeof(void));
编辑:问题的扩展。
如果 sizeof(void) 在 GCC 编译器中产生 1,则分配 1 个字节的内存并且指针 p 指向该字节并且 p++ 会递增到 0x2346?假设 p 是 0x2345。我说的是 p 而不是 *p。
类型void
没有大小;那将是一个编译错误。出于同样的原因,您不能执行以下操作:
void n;
编辑。令我惊讶的是,在 GNU C 中sizeof(void)
确实可以编译:
$ 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
是一个不完整的类型,你不能对不完整的类型使用 sizeof。
尽管void
可以代表一个类型,但它实际上不能保存一个值。因此,它在内存中没有大小。void
没有定义获取 a 的大小。
void
指针只是一种语言结构,表示指向无类型内存的指针。
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 有一个被视为1 的扩展名sizeof (void)
。 gcc 默认不是符合标准的 C 编译器,因此在其默认模式下,它不会警告sizeof (void)
. 即使对于完全符合 C 的编译器,也允许这样的扩展,但仍然需要诊断。
采用 void 的大小是GCC 扩展。
sizeof()
不能应用于不完整的类型。并且void
是无法完成的不完整类型。
在 C 中,sizeof(void) == 1
在 GCC 中,但这似乎取决于您的编译器。
在 C++ 中,我得到:
在函数'int main()'中: 第 2 行:错误:将“sizeof”无效应用到 void 类型 编译因 -Wfatal-errors 而终止。
对于问题的第二部分:注意 sizeof(void *)!= sizeof(void)。在 32 位拱形结构上,sizeof(void *) 为 4 个字节,因此 p++ 将相应设置。指针递增的量取决于它指向的数据。因此,它将增加 1 个字节。
大多数 C++ 编译器选择在尝试获取sizeof(void)
.
编译C时,gcc不符合,选择定义sizeof(void)
为1。可能看起来很奇怪,但有道理。当您进行指针运算时,添加或删除一个单位意味着添加或删除指向大小的对象。因此,定义sizeof(void)
为 1 有助于定义void*
为指向字节(无类型内存地址)的指针。p+1 == p when
否则,使用像p is这样的指针算术,你会出现令人惊讶的行为void*
。在 c++ 中不允许对 void 指针进行这种指针运算,但在使用 gcc 编译 C 时可以正常工作。
标准推荐的方法是char*
用于这种目的(指向字节的指针)。
使用 sizeof 时,C 和 C++ 之间的另一个类似差异发生在您定义空结构时,例如:
struct Empty {
} empty;
使用 gcc 作为我的 C 编译器sizeof(empty)
返回 0。使用 g++ 相同的代码将返回 1。
我不确定 C 和 C++ 标准在这一点上的规定,但我相信定义一些空结构/对象的大小有助于引用管理,以避免对不同连续对象的两个引用,第一个是空的,得到同一个地址。如果像通常那样使用隐藏指针实现引用,确保不同的地址将有助于比较它们。
但这只是通过引入另一个(空对象,甚至 POD 消耗至少 1 字节内存)来避免令人惊讶的行为(引用的极端情况比较)。
虽然 sizeof(void) 本身可能没有意义,但在进行任何指针数学运算时它很重要。
例如。
void *p;
while(...)
p++;
如果 sizeof(void) 被认为是 1,那么这将起作用。如果 sizeof(void) 被认为是 0,那么你会遇到一个无限循环。