当我创建int类型的方法时,编译器会在内存中保留X个位数。那么如何看待虚空类型呢? void类型占用多少位/字节?
答案 0 :(得分:13)
void类型不占用任何位。你不能声明一个void类型的变量。这样:
void a;
导致编译错误 void只是一个占位符,意思是“没有”一个返回void的函数返回什么,一个函数将void作为一个参数,不带任何参数。
但是,您可以声明void *:
类型的变量void* a;
这只是声明一个指向任何东西的指针。作为任何指针,它采用指针类型的大小,即sizeof(void *),在32位系统中通常等于4。
答案 1 :(得分:3)
我认为您对编译器如何存储返回值的假设可能过于通用。返回值会发生什么情况取决于语言,类型和硬件。
可能有一个'返回寄存器'可以保存返回值,因此不会占用任何内存。 “返回寄存器”也可以根据返回的类型指向内存中分配的内容。
我不明白为什么返回void的函数会为返回值分配内存。
答案 2 :(得分:3)
在x86架构上(使用gcc 3.4.6),int函数的返回值存储在eax寄存器中。浮点数通过XMM寄存器或ST0返回。 [编辑:谢谢巴斯蒂安伦纳德!]
Void函数根本不会将任何东西放入eax并返回。
#include <stdio.h>
int f1(void)
{
printf("f1\n");
return 9.0f;
}
void f2(void)
{
printf("f2\n");
}
double f3(void)
{
return 10.0;
}
int main(void)
{
int x = f1();
f2();
double y = f3();
return 0;
}
使用gcc -S构建:
main:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
andl $-16, %esp
movl $0, %eax
addl $15, %eax
addl $15, %eax
shrl $4, %eax
sall $4, %eax
subl %eax, %esp
call f1
movl %eax, -4(%ebp)
call f2
call f3
fstpl -16(%ebp)
movl $0, %eax
leave
ret
.size main, .-main
.section .note.GNU-stack,"",@progbits
.ident "GCC: (GNU) 3.4.6"
定义了f2:
f2:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
subl $12, %esp
pushl $.LC1
call printf
addl $16, %esp
leave
ret
.size f2, .-f2
和f1定义:
f1:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
subl $12, %esp
pushl $.LC0
call printf
addl $16, %esp
movl $9, %eax
leave
ret
如果其他人从不同版本的gcc中获得不同的代码,那么看XD会很有意思(也许在其他情况下,int函数会在堆栈上返回...)
我认为在所有实现中,void函数根本不返回任何内容。它要么单独留下返回寄存器,要么/或者什么都不丢弃(或进入)堆栈。
答案 3 :(得分:2)
函数返回void
,调用者不期望任何返回值,也不需要分配任何内容。 void
不是要返回的真实类型,它更多地表明编译器函数不返回任何内容。
在PC上,函数通过将它们放在特定的寄存器(int
)中来返回像eax
这样的简单值;编译器只需生成适当的代码即可检索此值。 (如果函数返回void
,则编译器不会生成此类代码。)
在其他体系结构上,调用者可能会隐式传递一个指向int
的参数,其中将返回值。
C和C ++标准没有规定这种低级别的东西。它可以由另一个标准指定,或者它可能只是一个惯例。
对于C#,我猜答案在于如何在CIL中获得返回值。
答案 4 :(得分:1)
C或C ++本身没有void类型(我对C#一无所知)。 void *是无类型指针。
答案 5 :(得分:0)
它只是一个未定义的指针类型,因此大小是您正在创建它的系统上任何其他指针的大小。