C语言按指定值拆分数组时循环外访问数组异常问题排查
代码错误说明
你的问题和数组作用域没有关系,代码一共存在3个核心语法/逻辑错误:
- 零长度数组越界访问
你声明的int iList_2small[] = {};、int iList_3large[] = {};属于零长度数组,编译时给这俩数组分配的空间大小为0,没有预留存储元素的内存位置。你后续往数组下标位置赋值属于越界访问未分配内存,是C语言标准定义的未定义行为:- 用
sizeof(iList_2small)算出来长度为0是正常结果,因为数组本身声明的大小就是0,sizeof是编译阶段就确定的值,不会因为你往内存里写了数据就改变 - 你能通过
iList_2small[10]读到56,纯粹是越界后刚好读到了原数组iList_1在栈上的相邻内存数据,不是这个数组真的存储了对应元素
- 用
- 计数器变量作用域错误
你把记录小数组写入位置的step_L2、step_L3定义在了for循环内部,每次循环迭代时这两个变量都会被重新初始化为0,导致每次写入都只覆盖下标0的位置,根本无法累计存储多个元素。 - 数组长度计算逻辑错误
C语言原生数组是固定长度的静态结构(除非手动调用malloc实现动态扩容),不会像Python列表一样随着元素插入自动增长长度,sizeof计算的是数组声明时占用的总内存大小,不会统计你越界写入的元素数量,因此不能用这种方式计算拆分后数组的实际元素个数。
修正方案
- 给两个拆分后的数组预分配足够的空间:因为拆分后元素总数最多和原数组相等,直接开和原数组等长的空间即可
- 把写入位置计数器挪到for循环外初始化,避免每次循环被重置
- 拆分完成后,直接用计数器的值作为两个小数组的实际长度,不要用
sizeof计算 - 打印数组时用实际长度作为循环上限,不要写死固定值
修正后的完整代码如下:
// Dividing a List into two Lists who's elements are <=X or >X int main() { int n; int boarder; int iList_1[] = {1, 23, 15, 90, 78, 234, 987, 2, 0, 13, 56}; // 预分配和原数组等长的存储空间,初始值全置0 int iList_2small[sizeof(iList_1)/sizeof(int)] = {0}; int iList_3large[sizeof(iList_1)/sizeof(int)] = {0}; // 计数器挪到循环外初始化 int step_L2 = 0; int step_L3 = 0; //Calculate the number of elements in the array size_t len1 = sizeof(iList_1) / sizeof(int); printf("The Array iList_1 is %llu long\n", len1); //Where to divide the array? printf("At what value should the array iList_1 be split? (ONLY INTEGERS ALLOWED)\n"); scanf("%i", &boarder); printf("\nConfirming boarder value of: %i \n\n", boarder); //Dividing the arrays at the boarder value for(n=0; n < len1; n++){ if(iList_1[n] <= boarder){ iList_2small[step_L2] = iList_1[n]; step_L2 += 1; } else { iList_3large[step_L3] = iList_1[n]; step_L3 += 1; } } // 计数器的值就是小数组的实际长度 size_t len2 = step_L2; size_t len3 = step_L3; //Only for demonstration purposes printf("\nThe length of the small list is \t %llu \t elements", len2); printf("\nThe length of the large list is \t %llu \t elements\n", len3); //Outputting the sorted arrays printf("Small list elements: "); for(n = 0; n < len2 ; n++){ printf("%i ", iList_2small[n]); } printf("\nLarge list elements: "); for(n = 0; n < len3; n++){ printf("%i ", iList_3large[n]); } return 0; }
补充说明:不要直接把Python动态列表的使用逻辑套用到C语言静态数组上,C语言数组声明后长度固定,写入元素时不能超过声明的长度,否则就会触发越界的未定义行为,可能出现各种不符合预期的运行结果。
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

