我是否正确地认为:
char *buff[500];
...创建了一个栈变量,并且:
char *buff = (char *)malloc(500);
...创建一个堆变量吗?
如果是这样,何时以及为什么会使用堆变量而不是栈变量,反之亦然。我知道栈更快,还有其他原因吗。
最后一个问题,主函数是否是堆栈上的堆栈帧?
我是否正确地认为:
char *buff[500];
...创建了一个栈变量,并且:
char *buff = (char *)malloc(500);
...创建一个堆变量吗?
如果是这样,何时以及为什么会使用堆变量而不是栈变量,反之亦然。我知道栈更快,还有其他原因吗。
最后一个问题,主函数是否是堆栈上的堆栈帧?
第一个创建了一个字符指针数组在栈中,大约 500*4字节
,第二个则在堆中分配了500个字符,并将栈的字符指针指向它们。
在栈中分配内存容易快速,但是栈的空间有限,而堆虽然较慢但更大。此外,栈分配的值在离开作用域后会被"删除",因此非常适合小的本地值,如原始变量。
如果您在栈中分配太多内存,可能会耗尽栈并崩溃,main
及其执行的所有函数都在栈中具有堆栈帧,并且所有函数的本地变量都存储在其中,因此过度调用函数可能会导致堆栈溢出。
通常的经验法则是将使用频繁且大于100字节的任何内容分配到堆中,将小变量和指针分配到栈中。
看到你写了
char *buff = (char *)malloc(500);
你可能是想表达
char buff[500]; instead of
char* buff[500];
在你的第一个例子中(因此你有一个字符数组,而不是指向字符的指针数组)
是的,“堆栈”上的分配速度更快,因为您只需增加存储在ESP寄存器中的指针。
如果您想要:
1)比堆栈可容纳的内存更大的内存(通常更早)
2)将由被调用函数分配的内存传递给调用函数,则需要堆变量。
你的buff
们不是等价的。
第一个 (char *buff[500]
) 是一个包含500个指针的数组;第二个 (char *buff = (char *)malloc(500)
) 是一个指针。
这个指针 (在堆栈上) 指向堆上的500个字节内存(如果malloc调用成功)。
指针数组位于堆栈上,它的指针没有被初始化。
除非使用C99,否则在使用栈时,数组的大小必须在编译时就已知。这意味着你不能这样做:
int size = 3; // somewhere, possibly from user input
char *buff[size];
但是使用“堆”(动态分配),您可以提供任何尺寸。这是因为内存分配是在运行时执行的,而不是硬编码到可执行文件中。
C标准中既没有“堆”也没有“栈”这两个词。相反,我们有四种存储期(其中两种是自动和分配的):
char buff[500]; // note the missing * to match the malloc example
within a function declares the object buff
as an array of char
and having automatic storage duration. The object will cease to be when the block where the object was declared, is exited.
char *buff = malloc(500); // no cast necessary; this is C
will declare buff
as a pointer to char
. malloc
will reserve 500 continuous bytes and return a pointer to it. The returned 500-byte object will exist until it is explicitly free
d with a call to free
. The object is said to have allocated storage duration.
这就是C标准的全部规定。它没有指定char buff[500]
需要从“堆栈”分配,或者需要存在堆栈。它也没有指定malloc
需要使用某种“堆”。相反,编译器可能会像下面这样内部实现char buff[500]
:
{
char *buff = malloc(500);
free(buff);
}
它可以推断出分配的内存未被使用,或仅被使用一次,因此使用基于堆栈的分配而不是实际调用 malloc
。
在实践中,大多数当前的编译器和环境将使用一种称为堆栈的内存布局来处理自动变量,而具有已分配存储期的对象则被称为来自“堆”,这是与有序堆栈相比的混乱无序的比喻,但它不一定是必须的。
这确实是在堆栈上分配的变量:
char buff[500]; // You had a typo here?
这是在堆上的:
char *buff = (char *)malloc(500);
你为什么要使用其中一个而不是另一个?
char *buff[500]
中,500
需要是编译时常量。如果500
在运行时计算,则无法使用它。最后:每个被调用的函数都有一个堆栈帧。 main
函数也不例外。它甚至不比程序中的其他函数更特殊,因为当程序开始运行时,第一段运行的代码位于C运行时环境
内。运行时准备好开始执行您自己的代码后,它会像调用任何其他函数一样调用main
。
堆变量可以动态创建,即您可以向用户请求一个大小并使用此大小分配新变量。
栈变量的大小必须在编译时知道。
正如您所说,栈变量分配和访问速度更快。因此,我建议每次在编译时知道大小时都使用它们。否则,您别无选择,必须使用malloc()
。
这两者并不等价。第一个是一个大小为500的数组(在堆栈上), 其中包含指向字符的指针。第二个是一个指向大小为500的内存块的指针,可以使用索引运算符。
char buff[500];
char *buff = (char *)malloc(sizeof(char)*500);
应优先使用堆栈变量,因为它们不需要释放。堆变量允许在作用域之间传递数据以及进行动态分配。
*
,对吗? - Jens Gustedtchar *buff
是一个变量,但它指向的内存(通过malloc
获得)不被称为变量;它被称为对象。在C语言中,变量具有名称、作用域、存储期和可能的链接性。每个变量都有一个关联的对象,其中包含(表示)它的值,但反之不成立。 - R.. GitHub STOP HELPING ICE