假设我将一个数组声明为 int myarray[5]
或将其声明为int*myarray=malloc(5*sizeof(int))
这两个声明是否会以字节数设置相等的内存量?不考虑前一个声明是针对堆栈的,而后者是针对堆的。
谢谢!
有一个根本的区别,这在您使用 的方式中可能并不明显myarray
:
int myarray[5];
声明一个由五个整数组成的数组,该数组是一个自动变量(并且它是未初始化的)。
int * myarray = malloc(5 * sizeof(int));
声明一个变量,它是指向 int 的指针(也作为自动变量),并且该指针使用库调用的结果进行初始化。该库调用承诺使结果指针指向一个足够大以存储五个连续整数的内存区域。
由于指针运算、数组到指针衰减和与 相同的约定a[i]
,*(a + i)
您可以以相同的方式使用这两个变量,即 as myarray[i]
。这当然是设计使然。
如果您正在寻找不同之处,那么以下可能会有所帮助:五个整数数组是一个对象,并且它具有确定的大小。相比之下,malloc
库调用不会创建任何对象。它只是留出足够的内存(并适当地对齐),但它可以分配更多的内存。
(在 C++ 中,内存和对象之间当然存在额外的区别。)
两者都不能保证准确分配5*sizeof(int)
字节,尽管两者都会给你至少那么多空间(假设没有分配失败或堆栈耗尽)。
在第一种情况下,堆栈变量可能被对齐填充和/或堆栈金丝雀包围(取决于编译选项)。这些可能导致堆栈指针被调整超过5*sizeof(int)
字节。
在第二种情况下,您int *
在堆栈(sizeof(int *)
字节)上分配 a,加上返回的空间malloc
。malloc
可能会以分配跟踪结构、对齐填充、链表指针等的形式分配额外的内存。因此,在这种情况下,您也不能保证准确分配5*sizeof(int)
字节。
如果您想非常精确地了解您的内存使用情况,该mmap
功能允许您从操作系统请求虚拟内存页面。您以这种方式请求的内存将恰好是您请求的数量(忽略内核中为跟踪这些分配而占用的空间)。
简短的回答:不,通常后者使用较小的较大内存。
长答案:内存管理肯定会使用一些额外的内存来管理返回的指针并能够跟踪它,并在稍后释放它,并且您声明一个额外的指针指向该内存。所以它的实际内存是sizeof(int*) + malloc_overhead
. 但在第一种情况下,您恰好使用 5 个 int(可能加上对齐)。
动态分配至少需要几个额外的字节;然而,除了 5int
大小的元素之外,指针变量还有很多字节,并且可能还有一些额外的字节来跟踪分配区域的大小,以便可以free
正确地 d 。