我有以下 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 收到以下警告消息:
test.c: In function ‘main’:
test.c:5:33: warning: division ‘sizeof (int *) / sizeof (int)’ does not compute the number of array elements [-Wsizeof-pointer-div]
5 | #define ARRAYSIZE(a) (sizeof(a))/(sizeof(a[0]))
| ^
test.c:15:35: note: in expansion of macro ‘ARRAYSIZE’
15 | printf("size of pArray: %ld\n", ARRAYSIZE(pArray));
| ^~~~~~~~~
test.c:11:8: note: first ‘sizeof’ operand was declared here
11 | int* pArray = array;
| ^~~~~~
test.c:5:33: warning: division ‘sizeof (int *) / sizeof (int)’ does not compute the number of array elements [-Wsizeof-pointer-div]
5 | #define ARRAYSIZE(a) (sizeof(a))/(sizeof(a[0]))
| ^
test.c:16:30: note: in expansion of macro ‘ARRAYSIZE’
16 | printf("size of p: %ld\n", ARRAYSIZE(p));
| ^~~~~~~~~
test.c:12:8: note: first ‘sizeof’ operand was declared here
12 | int* p = calloc(ARRAYSIZE(array), sizeof(int));
| ^
以下是程序输出:
size of array: 5
size of pArray: 2
size of p: 2
size of pArray: 1
size of p: 1
从程序输出中可以明显看出,只有当以数组名称作为参数调用宏时,我才能得到正确的值。但是,数组名不是指向数组第一个元素的指针吗?如果是这样,使用数组名称调用宏(产生正确的结果)与指向堆上数组的指针(不会产生正确的结果)之间的本质区别是什么?
从源代码中可以看出,我尝试了两种宏方法来获取在堆上创建的数组的大小,但没有成功。所以下一个问题是,是否有可能在 C 编程中使用
calloc(
) 获取在堆上创建的数组的大小?蒂亚
malloc
/
calloc
/
realloc
返回的指针指向多少分配的内存。程序员应该自己跟踪这一点。在您的示例中,由于
p
和
pArray
具有类型
int *
sizeof(p)
和
sizeof(pArray)
为您提供
int *
类型的大小,在您的系统上最有可能为 8。
但是,数组名不就是指向数组第一个元素的指针吗?不,数组名称是一个数组,但是在大多数情况下,数组“衰减”为指向其第一个元素的指针。不发生这种情况的一种情况是当数组是
sizeof
运算符的操作数时,因此由于 array
具有数组类型,因此 sizeof(array)
给出整个数组的大小。
有一些标准化方法可以了解
malloc()
和朋友 (realloc
) 返回的内存块的分配大小。在 GNU/Linux 上,函数
malloc_usable_size()
malloc_size()
和 malloc_good_size()
malloc_usable_size()
-std=gnu99
而不是
-std=c99
进行编译(通常是 -std=gnuXX
而不是
-std=cXX
)。
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <malloc.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* p = calloc(ARRAYSIZE(array), sizeof(int));
assert(p != NULL);
printf("Allocated size: %zu\n", malloc_usable_size(p));
free(p);
return 0;
}
结果:
Allocated size: 24