C语言乐园:结构体、野指针与数组链表的奇妙对决


🎮 C语言乐园:结构体、野指针与数组链表的奇妙对决 🎮


一、结构体 vs 共联体:百宝箱 vs 变形金刚 🧰🤖
  1. 结构体(Struct):百宝箱
    定义:把不同类型的变量打包成一个“箱子”,每个成员独立占坑!
    语法

    struct 学生档案 {
        char 姓名[20];  // 姓名占20字节
        int 年龄;       // 年龄占4字节
        float 成绩;     // 成绩占4字节
    };  // 总大小:28字节(可能加对齐填充)
    

    使用场景

    struct 学生档案 小明 = {"小明", 18, 90.5};
    printf("%s考了%.1f分", 小明.姓名, 小明.成绩);  // 输出:小明考了90.5分
    

    特点

    • 成员内存独立,互不干扰。
    • 像百宝箱,能装各种宝贝,但占空间较大。
  2. 共联体(Union):变形金刚
    定义:所有成员共用同一块内存,同一时间只能“变身”成一种形态!
    语法

    union 多功能数据 {
        int 整数;
        float 小数;
        char 字符;
    };  // 总大小 = 最大成员(float占4字节)
    

    使用场景

    union 多功能数据 数据;
    数据.整数 = 65;
    printf("%c", 数据.字符);  // 输出:A(65的ASCII值)
    

    特点

    • 内存共享,修改一个成员会影响其他成员。
    • 像变形金刚,省内存但一次只能用一个形态!

二、野指针:C语言中的“幽灵刺客” 👻⚡️
  1. 什么是野指针

    • 指向无效内存地址的指针,像无家可归的幽灵!
    • 危害:轻则程序崩溃,重则数据被篡改(黑客狂喜😈)。
  2. 野指针的四大成因

    • ① 未初始化的指针
      int *p;  // p指向随机地址(可能是系统禁区!)
      *p = 10; // 程序卒:Segmentation fault!
      
    • ② 释放后未置空
      int *p = (int*)malloc(sizeof(int));
      free(p);  // p变成“悬空指针”
      *p = 20;  // 操作已释放的内存,系统震怒!
      
    • ③ 指针越界访问
      int arr[3] = {1,2,3};
      int *p = &arr[2];
      p += 2;  // 越界指向未知区域
      *p = 666; // 危险操作!
      
    • ④ 返回局部变量地址
      int* 危险函数() {
          int a = 100;
          return &a;  // 函数结束,a的内存被回收
      }
      int *p = 危险函数();
      printf("%d", *p); // 输出:乱码或崩溃!
      
  3. 如何防御野指针

    • 规则1:指针出生时立刻初始化!
      int *p = NULL;  // 先让它指向“虚无”
      
    • 规则2free后立刻置空!
      free(p); 
      p = NULL;  // 从幽灵变回普通人
      
    • 规则3:避免返回局部变量地址,用static或动态内存。

三、数组 vs 链表:图书馆 vs 快递链 📚📦
对比项数组链表
内存分配连续内存(像图书馆书架)分散内存(像快递包裹,每个节点记录下一个地址)
大小固定大小(声明时确定)动态扩展(随时增删节点)
访问速度⚡️闪电侠:直接通过下标访问(O(1))🐢乌龟侠:从头遍历(O(n))
插入/删除😫痛苦:需要移动大量元素(O(n))😄轻松:改指针即可(O(1))
内存开销只存数据每个节点额外存指针(空间换时间)
缓存友好性✅连续内存,CPU缓存命中率高❌内存分散,缓存命中率低

生动例子

  • 数组:图书馆的书架

    int 书架[5] = {1, 2, 3, 4, 5};  
    printf("第三本书:%d", 书架[2]);  // 直接找到!
    

    想插入新书?需要把后面的书全部往后挪!😱

  • 链表:快递包裹链

    struct 快递节点 {
        int 包裹号;
        struct 快递节点 *下一站;
    };
    struct 快递节点 *头节点 = malloc(sizeof(struct 快递节点));
    头节点->包裹号 = 1001;
    头节点->下一站 = NULL; // 暂时只有一个包裹
    

    插入新包裹?只需修改指针,无需移动其他包裹!🚚


四、总结:选择合适的工具 🛠️
  • 结构体:需要打包多种数据时(如学生档案)。
  • 共联体:省内存,且同一时间只用一种数据(如网络协议解析)。
  • 野指针:牢记“初始化、置空、别越界”三大法则!
  • 数组 vs 链表
    • 需要快速访问?选数组!
    • 频繁增删数据?选链表!

最后的小测试

int *p;  
p = (int*)malloc(sizeof(int));  
*p = 10;  
free(p);  
printf("%d", *p);  // 这是什么行为?  

答案:野指针作妖!💣 记得free后把p = NULL哦!


用好这些知识,你的C语言代码会从“定时炸弹”变成“瑞士手表”!⌚✨

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FightingLod

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值