80

这个陈述会产生什么?

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

编辑:问题的扩展。

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

4

10 回答 10

62

类型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
于 2009-11-03T09:31:42.357 回答
43

如果您使用的是 GCC 并且您没有使用删除编译器特定扩展的编译标志,sizeof(void)则为 1。 GCC 有一个非标准扩展可以做到这一点。

一般来说,void是一个不完整的类型,你不能对不完整的类型使用 sizeof。

于 2009-11-03T09:35:35.800 回答
16

尽管void可以代表一个类型,但它实际上不能保存一个值。因此,它在内存中没有大小。void没有定义获取 a 的大小。

void 指针只是一种语言结构,表示指向无类型内存的指针。

于 2009-11-03T09:33:44.337 回答
14

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 的编译器,也允许这样的扩展,但仍然需要诊断。

于 2015-02-01T03:17:20.860 回答
11

采用 void 的大小是GCC 扩展

于 2009-11-03T09:39:02.043 回答
6

sizeof()不能应用于不完整的类型。并且void是无法完成的不完整类型。

于 2009-11-03T09:34:13.147 回答
3

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

在 C++ 中,我得到:

在函数'int main()'中:
第 2 行:错误:将“sizeof”无效应用到 void 类型
编译因 -Wfatal-errors 而终止。
于 2009-11-03T09:33:27.937 回答
0

对于问题的第二部分:注意 sizeof(void *)!= sizeof(void)。在 32 位拱形结构上,sizeof(void *) 为 4 个字节,因此 p++ 将相应设置。指针递增的量取决于它指向的数据。因此,它将增加 1 个字节。

于 2009-11-03T09:57:19.360 回答
-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 字节内存)来避免令人惊讶的行为(引用的极端情况比较)。

于 2013-03-21T09:34:36.400 回答
-2

虽然 sizeof(void) 本身可能没有意义,但在进行任何指针数学运算时它很重要。

例如。

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

如果 sizeof(void) 被认为是 1,那么这将起作用。如果 sizeof(void) 被认为是 0,那么你会遇到一个无限循环。

于 2011-11-17T19:59:03.910 回答