C语言中指针、结构体与函数结合使用的错误排查求助
C语言结构体柔性数组引发的段错误及修复
你的代码出现打印异常和段错误的核心原因是:Hero结构体中的char name[]是柔性数组成员,栈上直接声明Hero flash;时,这个柔性数组没有分配任何内存空间。执行strcpy(flash.name, "The Flash")会直接越界写入栈内存,破坏其他变量的内存布局,进而引发各种异常。
以下是两种可行的修复方案:
方案一:给name指定固定长度
如果英雄名称的长度是可预估的,直接给name字段设置固定大小,栈上声明的结构体就会为其分配足够空间,避免内存越界。
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct { int power; int life; char name[64]; // 根据需求调整固定长度 } Hero; void attackHero(Hero *hero, int *power) { hero->life -= *power; // 用->简化指针访问结构体成员,等价于(*hero).life printf("Damage: %d\n", *power); printf("Attacked hero: %s\n", hero->name); printf("Hero's remaining life: %d\n", hero->life); } int main () { Hero flash; flash.power = 250; flash.life = 500; strcpy(flash.name, "The Flash"); Hero batman; batman.power = 380; batman.life = 700; strcpy(batman.name, "Batman arkham knight"); attackHero(&flash, &batman.power); return 0; }
方案二:使用动态内存分配(适用于长度不确定的场景)
柔性数组的正确用法是配合动态内存分配,先分配结构体本身的内存,再额外为name字段分配空间,总分配大小为sizeof(Hero) + 字符串长度 + 1(+1是为了存储字符串终止符\0)。
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct { int power; int life; char name[]; // 柔性数组 } Hero; void attackHero(Hero *hero, int *power) { hero->life -= *power; printf("Damage: %d\n", *power); printf("Attacked hero: %s\n", hero->name); printf("Hero's remaining life: %d\n", hero->life); } int main () { const char* flash_name = "The Flash"; // 分配结构体+名称的总内存 Hero *flash = malloc(sizeof(Hero) + strlen(flash_name) + 1); if (!flash) { // 检查内存分配是否成功 perror("malloc failed"); return 1; } flash->power = 250; flash->life = 500; strcpy(flash->name, flash_name); const char* batman_name = "Batman arkham knight"; Hero *batman = malloc(sizeof(Hero) + strlen(batman_name) + 1); if (!batman) { perror("malloc failed"); free(flash); // 避免内存泄漏 return 1; } batman->power = 380; batman->life = 700; strcpy(batman->name, batman_name); attackHero(flash, &batman->power); // 释放动态分配的内存 free(flash); free(batman); return 0; }
额外说明
- 栈上声明的结构体不能直接使用柔性数组,因为
sizeof(Hero)不会包含柔性数组的空间,必须通过动态内存分配为其补充空间。 hero->life是指针访问结构体成员的简化写法,和(*hero).life功能完全一致,代码更简洁。- 动态分配内存后必须检查返回值,避免分配失败导致空指针操作;使用完内存后要记得释放,防止内存泄漏。
内容的提问来源于stack exchange,提问作者Diego
相关产品推荐
相关产品推荐

