如何获取C语言中堆上分配的数组大小?
数组名与指针的差异及堆数组大小的获取问题
先结合你的代码、编译警告和运行结果,拆解核心问题:
你的测试代码
#include <stdio.h> #include <stdlib.h> #include <assert.h> #define ARRAYSIZE(a) (sizeof(a))/(sizeof(a[0])) #define ARRAYSIZEWITHPTR(a) (&(a)[1] - a) int main (void){ int array[5] = {1,2,3,4,5}; int* pArray = array; int* p = calloc(ARRAYSIZE(array), sizeof(int)); assert(NULL != p); printf("size of array: %ld\n", ARRAYSIZE(array)); printf("size of pArray: %ld\n", ARRAYSIZE(pArray)); printf("size of p: %ld\n", ARRAYSIZE(p)); printf("size of pArray: %ld\n", ARRAYSIZEWITHPTR(pArray)); printf("size of p: %ld\n", ARRAYSIZEWITHPTR(p)); free(p); return 0; }
编译警告与输出分析
gcc的警告已经点明问题:你用指针作为ARRAYSIZE的参数时,实际在计算sizeof(指针)/sizeof(int),这和数组元素个数毫无关系。运行输出的结果差异,本质是数组名和指针的核心区别:
数组名≠指针
数组名在多数场景下会隐式转换为指向首元素的指针,但在sizeof、&这类操作符作用时,它会保留「数组类型」的身份:- 传入数组名
array时,sizeof(array)计算的是整个数组的字节数(你的例子中是5*sizeof(int)=20字节),除以sizeof(array[0])(4字节)得到正确的元素个数5。 - 传入指针
pArray或p时,sizeof(pArray)计算的是指针变量本身的字节数(64位系统下通常是8字节),除以sizeof(int)(4字节)得到2,这就是输出中size of pArray:2、size of p:2的原因。
- 传入数组名
第二个宏的无效性
ARRAYSIZEWITHPTR(a)的逻辑是&(a)[1]-a:- 当
a是指针时,(a)[1]等价于*(a+1),&(a)[1]就是a+1,所以(a+1)-a的结果是1(指针减法返回元素个数差),这就是输出size of pArray:1、size of p:1的原因——这个宏完全无法获取数组大小。
- 当
堆数组能否直接获取大小?
标准C中,无法通过calloc/malloc返回的指针直接获取堆数组的大小。因为堆内存的管理信息(比如分配的字节数)是由编译器/运行时库内部维护的,不会暴露给用户程序。
解决方案
只能手动记录堆数组的大小:
- 用单独变量保存元素个数:
size_t arr_len = ARRAYSIZE(array); int* p = calloc(arr_len, sizeof(int)); // 后续需要大小时直接使用arr_len - 用结构体绑定指针和大小,方便管理:
typedef struct { int* data; size_t len; } IntArray; IntArray heap_arr; heap_arr.len = ARRAYSIZE(array); heap_arr.data = calloc(heap_arr.len, sizeof(int));
内容的提问来源于stack exchange,提问作者Vinod
相关产品推荐
相关产品推荐

