C语言中结构体含多成员时结构体数组无法排序的问题
结构体多成员时归并排序崩溃的原因与解决方法
当结构体仅包含int number成员时,归并排序代码可以正常运行,但为结构体添加char name[101]成员后,程序运行时会崩溃并返回非0值。
崩溃原因
核心问题是临时数组tempArr的大小计算错误:
合并区间[left, right]包含的元素总数是right - left + 1个,但代码里定义临时数组为name tempArr[right - left];,数组大小少了1。
当结构体只有单个int成员时,栈内存的越界写入可能刚好没有破坏关键数据(属于未定义行为,只是碰巧没崩溃);但结构体新增char[101]成员后,单个结构体占用内存大幅增加,越界写入会直接破坏栈上的其他数据(比如函数的返回地址、其他局部变量),触发程序崩溃。
另外还有两个非崩溃但不符合C语言规范的问题:
- C语言中,结构体类型
struct name不能直接简写为name,需要通过typedef定义别名,否则所有使用name的地方都要写成struct name - 函数参数里的
name arr[5]会被编译器视为name *arr,写name arr[]或name *arr更符合语义
修复步骤
- 修正临时数组大小:将
name tempArr[right - left];改为name tempArr[right - left + 1];,确保能容纳所有待合并的元素 - 规范结构体类型使用:添加
typedef定义结构体别名,或者在代码中统一使用struct name - 可选优化:将函数参数的数组写法改为指针形式,提升代码规范性
修复后的完整代码
#include <stdio.h> #include <string.h> // 添加typedef,让name可以直接作为结构体类型名 typedef struct name{ int number; char name[101]; } name; // 数组参数改为指针形式,更规范 void mergeSort(name *arr, int left, int right){ if(left == right){ return; } int middle = (right - left) / 2 + left; mergeSort(arr, left, middle); mergeSort(arr, middle+1, right); int leftIdx = left, leftLimit = middle, rightIdx = middle+1, rightLimit = right, tempIdx = 0; // 修正临时数组大小:right - left + 1 name tempArr[right - left + 1]; while(leftIdx <= leftLimit && rightIdx <= rightLimit){ // 依然按number字段排序,不受新增成员影响 if(arr[leftIdx].number < arr[rightIdx].number){ tempArr[tempIdx] = arr[leftIdx]; tempIdx++; leftIdx++; }else{ tempArr[tempIdx] = arr[rightIdx]; tempIdx++; rightIdx++; } } while(leftIdx <= leftLimit){ tempArr[tempIdx] = arr[leftIdx]; tempIdx++; leftIdx++; } while(rightIdx <= rightLimit){ tempArr[tempIdx] = arr[rightIdx]; tempIdx++; rightIdx++; } tempIdx = 0; for(int i=left; i<=right; i++){ arr[i] = tempArr[tempIdx]; tempIdx++; } } int main(){ name arr[5]; // 示例输入逻辑:可以同时输入number和name for(int i=0; i<5; i++){ scanf("%d %s", &arr[i].number, arr[i].name); } mergeSort(arr, 0, 4); // 输出排序后的结果 for(int i=0; i<5; i++){ printf("%d %s\n", arr[i].number, arr[i].name); } return 0; }
说明
修复后,无论结构体有多少个成员,只要排序逻辑是基于number字段(或你指定的其他字段),归并排序都能正常运行。如果需要按其他字段排序,只需要修改合并时的比较条件即可。
内容的提问来源于stack exchange,提问作者Jeremy Edward
相关产品推荐
相关产品推荐

