C语言跨函数获取数组大小及sizeof取值差异问题咨询
C语言函数内计算数组长度失效问题答疑
场景说明
- 场景1:在main函数中声明并初始化数组后传入
function1,尝试不在main中预先计算元素总数,直接在function1内部统计数组元素个数,方案未生效 - 场景2、3:在main函数中预先计算数组元素个数,作为参数传入
function2,方案可正常运行,其中场景3为场景2的紧凑写法
疑问解答
1. main函数内sizeof(a)可正确返回数组总内存大小的原因
不存在main函数的特殊处理机制,核心原因是数组类型退化为指针是有明确触发条件的,并非所有场景下数组名都会变成指针。
C语言标准规定,只有当数组名出现在以下三类场景时,才会退化为指向数组首元素的指针:
- 作为实参传入函数
- 作为
sizeof、_Alignof运算符以外的操作数 - 被显式转换为对应指针类型
在main函数的作用域中,double a[] = {1.32, 2, 5.52, 9.99};是完整的数组定义,编译器编译阶段就明确其类型为double[4],总长度32字节。此时执行sizeof(a)时,操作数是完整的数组类型,没有触发退化规则,因此会直接返回整个数组占用的总内存字节数,自然可以正确计算元素个数。
而数组作为实参传入函数时,已经触发了退化规则,进入函数后形参a的类型会被直接调整为double *,不再是数组类型,自然无法通过sizeof拿到数组总长度。
2. GCC给出编译警告的原因
GCC在静态编译阶段就可以识别这类确定的逻辑错误:函数形参中的double a[]只是语法糖,编译时会被直接调整为指针类型double *,此时函数内执行sizeof(a)得到的永远是指针的内存大小(64位架构下为8字节),不可能得到开发者预期的传入数组的实际总长度,计算出的元素个数恒为1,和代码逻辑的预期目标完全不符,因此会直接抛出对应警告,不需要运行即可判定该写法存在错误。
测试代码
#include <stdio.h> void function1(double a[]) { int numOfElements = sizeof(a) / sizeof(a[0]); printf("\n ---> Size of array in function1: %d\n", sizeof(a)); // Some operations... } void function2(double a[], int numOfElements) { // Some operations... } int main() { double a[] = {1.32, 2, 5.52, 9.99}; // Case 1 function1(a); // Case 2 int numOfElements = sizeof(a) / sizeof(a[0]); function2(a, numOfElements); // Case 3 - a more compact version of Case 2 function2(a, sizeof(a) / sizeof(a[0])); printf("\n ---> Size of array in main: %d\n", sizeof(a)); return 0; }
运行输出与编译警告

内容的提问来源于stack exchange,提问作者Vladimir
相关产品推荐
相关产品推荐

