calloc函数返回值可赋值类型:数组指针、元素指针或二者均可?
calloc返回值的合法赋值类型分析
根据C17标准草案7.22.3.2,calloc函数的原型为:
void *calloc(size_t nmemb, size_t size);
它的作用是分配一块能容纳nmemb个大小为size的对象的数组空间,并且会将空间内的所有位初始化为0。
常见用法
对于分配T类型的数组,最常见的写法是将返回值赋值给指向元素的指针:
T *p = calloc(nmemb, sizeof(T));
或者分开初始化与赋值:
T *p; p = calloc(nmemb, sizeof(T));
指向数组的指针写法
考虑到calloc本质是为数组分配空间,以下将返回值赋值给指向数组的指针的写法同样合法:
T (*arrp)[nmemb] = calloc(nmemb, sizeof(T));
或者分开写:
T (*arrp)[nmemb]; arrp = calloc(nmemb, sizeof(T));
注:每组的第一种写法严格来说属于初始化,而非赋值操作。
核心问题解答
calloc的返回值是void*类型,根据C标准规则,void*可以隐式转换为任意对象指针类型。因此:
- 既可以赋值给指向数组元素的指针(T*)
- 也可以赋值给指向数组的指针(T (*)[])
两种写法均符合C17标准要求,且在GCC(编译参数gcc -std=c17 -pedantic -Wall -Wextra)和MSVC(编译参数cl /std:c17 /Wall)环境下都能正常编译,运行输出符合预期。
补充背景知识
对于T类型数组arr,以下三个表达式的类型与值特点:
arr:退化前类型为T[],退化后为T*(指向数组首元素)&arr[0]:类型为T*,与退化后的arr值相同&arr:类型为T (*)[](&运算符阻止数组类型退化,指向整个数组)
前两者的地址值完全相同,C标准仅保证(void *)&arr == (void *)&arr[0]成立,理论上&arr的地址表示可能与前两者不同,但转换为void*后必须相等。
内容的提问来源于stack exchange,提问作者Lover of Structure
相关产品推荐
相关产品推荐

