假设我声明一个数组为 int myarray[5]
或者将其声明为 int*myarray=malloc(5*sizeof(int))
这两个声明是否设置了相等数量的内存(以字节为单位)? 不考虑前一个声明是用于堆栈,而后者是用于堆。
谢谢!
在使用myarray
时,有一个基本的区别可能并不明显:
int myarray[5];
声明了一个由五个整数组成的数组,该数组是自动变量(且未初始化)。
int *myarray = malloc(5 * sizeof(int));
声明了一个指向整数的指针变量(也是自动变量),该指针被初始化为一个库调用的结果。该库调用承诺将导致所得到的指针指向一个足够大的存储五个连续整数的内存区域。
由于指针算术、数组指针衰减以及a[i]
与*(a+i)
等价的约定,您可以像使用myarray[i]
一样使用这两个变量。这当然是有意设计的。
如果您正在寻找区别,那么以下内容可能会有所帮助:五个整数数组是一个单一的对象,它具有确定的大小。相比之下,malloc
库调用不会创建任何对象。它只是分配了足够的内存(并适当对齐),但它也可能分配更多的内存。
(在C++中,当然还有内存和对象之间的附加区别。)
简短回答:通常情况下,后者使用比较少但更大的内存。
详细回答:
内存管理需要使用一些额外的内存来管理返回的指针,并能够跟踪它,在稍后的时间释放它,您需要声明一个额外的指针来指向该内存。所以它的实际内存大小是sizeof(int*) + malloc_overhead
。但在第一种情况中,您恰好使用了5个int(加上对齐可能)。
两种方法都不能保证确切地分配 5*sizeof(int)
字节,但两种方法都至少给您提供了这么多的空间(假设没有分配失败或栈耗尽)。
在第一种情况下,堆栈变量可能被对齐填充和/或堆栈安全标识包围(具体取决于编译选项)。这可能导致堆栈指针调整超过 5*sizeof(int)
字节。
在第二种情况下,您在堆栈上分配了一个 int *
(sizeof(int *)
字节),加上 malloc
返回的空间。 malloc
可能会以分配跟踪结构、对齐填充、链表指针等形式分配额外的内存。因此,在这种情况下,您也不能保证确切地分配 5*sizeof(int)
字节。
如果您想非常精确地使用内存,则 mmap
函数允许您从操作系统请求虚拟内存页面。以这种方式请求的内存将是您请求的数量(忽略用于跟踪这些分配的内核中占用的空间)。
int* myarray = new int [5]
。 - Konstantin Schubert