根据标准(C17草案,7.22.3.2),
calloc
void *calloc(size_t nmemb, size_t size);
“为
nmemb
对象数组分配空间,每个对象的大小为size
”(并将所有位初始化为零)。
对于
calloc
的T
数组,我只见过这样的代码:
T *p = calloc(nmemb, sizeof(T));
但是考虑到
calloc
为 array 分配空间,以下也应该没问题:
T (*arrp)[nmemb] = calloc(nmemb, sizeof(T));
calloc
的结果可以分配给什么类型,指向数组的指针(类型T (*)[]
),指向数组中包含的类型的指针(类型T *
),还是其中之一?
以下代码
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int (*iarrp)[5];
int *ip;
float (*farrp)[1];
float *fp;
int i;
iarrp = calloc(5, sizeof(int));
for (i = 0; i < 5; ++i)
(*iarrp)[i] = -i;
ip = calloc(5, sizeof(int));
for (i = 0; i < 5; ++i)
ip[i] = i + 100;
for (i = 0; i < 5; ++i)
printf("%d: %d, %d\n", i, (*iarrp)[i], ip[i]);
farrp = calloc(1, sizeof(float));
(*farrp)[0] = 5.5;
fp = calloc(1, sizeof(float));
*fp = 6.6;
printf("%.2f, %.2f\n", (*farrp)[0], *fp);
free(iarrp);
free(ip);
free(farrp);
free(fp);
return 0;
}
使用 GCC (
gcc -std=c17 -pedantic -Wall -Wextra
) 和 MSVC (cl /std:c17 /Wall
) 对我来说编译得很好,输出符合预期:
0: 0, 100
1: -1, 101
2: -2, 102
3: -3, 103
4: -4, 104
5.50, 6.60
问这个问题的背景是这样的:对于一个类型为
arr
的数组T[]
,有以下三个表达式
arr
;类型:T[]
(衰减前),T *
(衰减后)&arr[0]
;类型:T *
arr
衰减为 &arr
;类型:T (*)[]
&
防止腐烂前两者具有相同的值。理论上,第三个表达式的值可以与前两个表达式不同,尽管我知道这种情况并不常见。该标准仅保证
(unsigned char *)&arr == (unsigned char *)&arr[0]
成立。
calloc
返回的动态分配内存没有有效类型,根据C 2018 6.5 6。在C语义中,它只是一个可用于任何对象类型的内存区域。
它可以通过使用非字符类型向其中存储值来获取有效类型。