这句话会产生什么?
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。
Answers:
类型void
没有大小。那将是一个编译错误。出于同样的原因,您不能执行以下操作:
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
void
在1989年ANSI C标准引入之前,它就不存在了,该标准sizeof (void)
违反了约束。
如果您使用的是GCC,并且没有使用删除编译器特定扩展的编译标志,sizeof(void)
则为1。GCC具有执行此操作的非标准扩展。
通常,void
它是不完整的类型,您不能将sizeof用于不完整的类型。
-Wpointer-arith
由隐含-pedantic
。我一直都习惯-pedantic
。:)
尽管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的扩展名被视为sizeof (void)
1。gcc默认情况下不是兼容的C编译器,因此在其默认模式下它不会发出警告sizeof (void)
。即使对于完全符合标准的C编译器,也可以使用这样的扩展名,但是仍然需要诊断。
sizeof(void) == 1
与指针上的void
指针算法保持一致,这也是gcc扩展。从他们的文档中引用:A consequence of this is that sizeof is also allowed on void and on function types, and returns 1.
。但是默认情况下,对于C,诊断消息仍应存在,因为Standard要求它。
-std=c11 -pedantic
。使用此类选项,它会发出所需的诊断信息。
sizeof()
不能应用于不完整的类型。并且void
是无法完成的不完整类型。
在C中,sizeof(void) == 1
在GCC中,但这似乎取决于您的编译器。
在C ++中,我得到:
在函数'int main()'中: 第2行:错误:将'sizeof'无效应用到void类型 由于-Wfatal-errors,编译终止。
对于问题的第二部分:请注意,sizeof(void *)!= sizeof(void)。在32位的Arch上,sizeof(void *)是4个字节,因此p ++会被相应地设置。指针的增加量取决于它所指向的数据。因此,它将增加1个字节。
T*
被增加sizeof(T)
(和不 sizeof(T*)
,这将几乎始终是相同的,除了也许函数指针),当它被递增。当然void
是例外(同样,启用了GCC扩展时也是例外)。
void*
指针指向的数据大小为1个字节?sizeof (void)
是违反约束的。(gcc扩展名将其视为1。)
虽然sizeof(void)本身可能没有任何意义,但是在进行任何指针数学运算时,这一点很重要。
例如。
void *p;
while(...)
p++;
如果将sizeof(void)视为1,那么它将起作用。如果将sizeof(void)视为0,则您遇到无限循环。
unsigned char*
。
char
不能保证为1个字节。我曾在将其设置为32位的系统上工作。
char
保证为1个字节。如果您使用的char
是32位系统,则该系统上的一个字节为32位(CHAR_BIT == 32
)。这就是C标准定义“字节”的方式。C标准,段落6.5.3.4 2和4道:“sizeof
操作者产生其操作数的大小(以字节计)[...]当。sizeof
被施加到具有类型的操作数char
,unsigned char
或signed char
,(或合格的版本体)结果是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)
与C ++中一样,没有在C中定义。在这一点上,GCC根本不符合要求,并且指针上的指针算法void
也没有定义,这void* p; p++;
是无效的。使用该-pedantic
标志编译时,即使是GCC也会给您警告。您还错了GCC for C ++的默认行为:默认情况下,这被视为error。
struct
定义是语法错误;gcc的支持是扩展。它们可能在C ++中有效。我不确定。