C语言使用sizeof计算数组长度编译失败、结果异常求解
C语言数组长度计算异常原因说明
核心规则
C语言中数组作为实参传入函数时,会自动退化为指向数组首元素的指针,函数内部的形参只存储数组首地址,不携带数组的总长度信息,这是你遇到所有异常的根本原因。
你在全局作用域定义的数组:
const char array[] = {'t', 'h', 'i', 's', 'i', 's', 'm', 'y', 't', 'e', 'x', 't', '\0'};
是完整的数组类型,总占13字节内存(包含末尾的'\0'结束符),在这个全局作用域下用sizeof计算长度是可以得到正确结果的,但传入函数后规则就发生了变化。
三种写法的现象解释
- 无法编译的写法
size_t len = sizeof(array) / sizeof(array[0]);
如果你是在函数形参列表位置用这个表达式尝试声明数组形参长度,此时形参数组属于不完整类型,编译器无法计算sizeof取值,会直接抛出编译错误。如果是在函数内部写这行代码,本身不会编译失败,但计算结果和第二种错误写法完全一致,拿不到真实数组长度。 - 返回长度为4的错误写法
size_t len = sizeof(array) / sizeof(char);
函数内部的形参array是char*类型的指针,32位编译环境下指针本身固定占4字节内存,sizeof(array)拿到的是指针的大小,不是整个数组的大小,除以sizeof(char)(固定为1)后结果为4,和数组真实长度完全无关。如果是64位环境,这个计算结果会变成8,同样是错误值。 - 硬编码
len = 12可正常运行
你手动指定的12刚好是数组中'\0'之前的有效字符个数,循环遍历范围刚好覆盖所有需要统计的字符,所以功能可以正常运行。
正确实现方案
你可以根据场景选以下任意一种方式获取数组长度:
- 额外传参携带长度(C语言通用方案)
在数组定义的全局/调用方作用域先计算好真实长度,再作为参数传入函数:// 调用方作用域计算长度,减1是为了排除末尾的'\0',得到有效字符数12 size_t arr_len = sizeof(array) / sizeof(array[0]) - 1; count_chars(array, arr_len, counts); // 函数定义改为接收长度参数 void count_chars(const char *array, size_t len, unsigned int *counts) { for(size_t i = 0; i < len; i++){ counts[(int)array[i]]++; } } - 针对C字符串用strlen获取长度
你定义的数组以'\0'结尾,符合C字符串的格式要求,可以在函数内引入<string.h>头文件后直接用strlen计算有效字符长度:#include <string.h> void count_chars(const char *array, unsigned int *counts) { size_t len = strlen(array); // 自动统计到'\0'前的字符数,结果为12 for(size_t i = 0; i < len; i++){ counts[(int)array[i]]++; } } - 宏定义固定长度
如果数组长度是固定值,可以用宏统一定义长度,避免硬编码散落在代码各处:#define ARRAY_VALID_LEN 12 const char array[] = {'t', 'h', 'i', 's', 'i', 's', 'm', 'y', 't', 'e', 'x', 't', '\0'}; // 后续遍历直接使用ARRAY_VALID_LEN即可
内容的提问来源于stack exchange,提问作者Isto Vilhola
相关产品推荐
相关产品推荐

