首页 抖音热门文章正文

c语言学习从内存堆栈视角,给这段共用体union代码做个 "内存透视"

抖音热门 2025年08月27日 23:12 2 admin
c语言学习从内存堆栈视角,给这段共用体union代码做个 "内存透视"

从内存堆栈视角,给这段共用体代码做个 "内存透视"

#include <stdio.h>#include <string.h> union Data{   int i;   float f;   char  str[20];}; int main( ){   union Data data;            data.i = 10;   data.f = 220.5;   strcpy( data.str, "C Programming");    printf( "data.i : %d\n", data.i);   printf( "data.f : %f\n", data.f);   printf( "data.str : %s\n", data.str);    return 0;}

咱们先打个比方:共用体(union)就像一个 "多功能储物盒"—— 盒子只有一个,但可以放不同类型的东西(整数、浮点数、字符串),但每次只能放一种,新东西放进去会把旧的覆盖掉。而栈就像家里的临时置物台,这个盒子用完就收走,不占地方。

先看懂代码的 "迷惑行为"

这段代码定义了一个Data共用体,里面可以放整数i、浮点数f或字符串str。然后在main里创建了data变量,先存 10,再存 220.5,最后存字符串 "C Programming",然后打印这三个值。运行结果会很奇怪:

plaintext

data.i : 1917853767data.f : 4122360580327794860452759994368.000000data.str : C Programming

整数和浮点数都乱了,只有字符串正常。这不是 bug,而是共用体的特性!今天咱们就从内存角度扒开这个 "多功能盒子" 的秘密。

内存区域聚焦:栈是唯一舞台

C 程序内存的三大块里,这段代码只用到了栈:



  • 栈(Stack):像临时置物台,main函数运行时在这里给共用体变量分配空间,函数结束后自动释放。
  • 全局区和堆:这段代码没用到,暂时忽略。

逐行拆解:共用体在栈上的 "覆盖术"

1. 共用体定义:设计 "多功能盒子图纸"

c

运行

union Data {   int i;          // 整数(4字节)   float f;        // 浮点数(4字节)   char str[20];   // 字符串(20字节)};



  • 这是共用体的 "设计图纸",告诉编译器:这个盒子能放三种东西,但整个盒子的大小由最大的成员决定(这里str[20]最大,所以盒子总大小是 20 字节)。
  • 重点:图纸不占运行时内存,就像你画的 "多功能盒子" 设计图不会占地方。

2. 创建共用体变量:栈上分配 "20 字节盒子"

c

运行

int main() {   union Data data;  // 共用体变量   // ...}



  • 程序运行时,main函数的栈帧在上创建,给data分配了 20 字节的连续空间(因为str[20]是最大成员)。这个空间就是那个 "多功能盒子",所有成员都共用这 20 字节 —— 就像一个盒子,既可以当 4 字节的小格子用(存i或f),也可以当 20 字节的长格子用(存str)。
  • 栈帧里的data初始布局(20 字节,地址连续):
  • plaintext
┌─────────────────────────────────────┐│ 字节0 字节1 字节2 ... 字节19        │  ← 共20字节,初始值是栈上的随机垃圾└─────────────────────────────────────┘

3. 给共用体赋值:"新内容覆盖旧内容"

c

运行

data.i = 10;         // 第一步:存整数10data.f = 220.5;      // 第二步:存浮点数220.5(覆盖前面的10)strcpy(data.str, "C Programming");  // 第三步:存字符串(覆盖前面的220.5)



  • 第一步:存i=10
    整数i占 4 字节,往盒子的前 4 字节(字节 0-3)存入 10 的二进制(00000000 00000000 00000000 00001010)。此时字节 4-19 还是随机值。
  • 第二步:存f=220.5
    浮点数f也占 4 字节,会
    覆盖前 4 字节,存入 220.5 的二进制(浮点数有特殊编码规则)。此时前 4 字节已经不是 10 了,后面 16 字节还是随机值。
  • 第三步:存字符串"C Programming"
    字符串str占 20 字节,会从字节 0 开始逐个存入字符:'C',' ','P','r','o','g','r','a','m','m','i','n','g','\0'(共 14 个字符),剩下的字节 6-19 被填充 '\0'。这一步会
    覆盖整个 20 字节,包括前 4 字节 —— 所以之前存的i和f全被冲掉了!

4. 打印结果:"读的是同一块内存,但解析方式不同"

c

运行

printf("data.i : %d\n", data.i);   // 读前4字节,按整数解析printf("data.f : %f\n", data.f);   // 读前4字节,按浮点数解析printf("data.str : %s\n", data.str); // 读20字节,按字符串解析



  • 打印data.i:读前 4 字节(现在是 'C',' ','P','r' 的 ASCII 码),强行按整数规则解析,得到一个乱码数字(1917853767)。
  • 打印data.f:读前 4 字节,强行按浮点数规则解析,结果更离谱(因为这 4 字节本来是字符,不是浮点数编码)。
  • 打印data.str:读整个 20 字节,按字符串规则解析(直到 '\0'),所以正常显示 "C Programming"。
  • 就像你用收音机听 CD:CD 里存的是音乐(字符串),但你非要用收音机的方式(整数 / 浮点数解析)听,出来的只能是噪音。

5. 程序结束:栈帧 "整体清空"

c

运行

return 0;



  • main函数结束,栈帧被释放,data的 20 字节空间被回收(临时置物台上的盒子被收走)。

共用体的内存本质:"一块内存,多种解读"

  • 大小由最大成员决定:不管存什么,共用体变量的大小永远等于最大成员的大小(这里 20 字节)。
  • 成员共享同一块内存:新成员赋值会覆盖旧成员(因为地址重叠),所以同一时间只能用一个成员。
  • 解析方式决定值:同一块内存,按不同类型解析(整数 / 浮点数 / 字符串)会得到不同结果,就像同样的二进制,用 txt 打开是文字,用 jpg 打开可能是乱图。

关键结论:共用体是 "内存里的多面镜"

  • 共用体变量data在栈上占 20 字节,所有成员都共享这 20 字节 —— 这是和结构体最本质的区别(结构体成员各占空间,不重叠)。
  • 它的价值是 "节省内存":当你知道某块内存同一时间只会存一种类型时,用共用体比结构体更省空间(比如 20 字节 vs 28 字节(4+4+20))。
  • 但要小心 "覆盖陷阱":存新值会冲掉旧值,所以使用时必须清楚当前存的是什么类型,否则会读错数据(就像你得知道盒子里现在放的是饼干还是手机,否则可能会一口咬下去)。
#include <stdio.h>#include <string.h> union Data{   int i;   float f;   char  str[20];}; int main( ){   union Data data;            printf( "Memory size occupied by data : %d\n", sizeof(data));    return 0;}
#include <stdio.h>#include <string.h> union Data{   int i;   float f;   char  str[20];}; int main( ){   union Data data;            data.i = 10;   printf( "data.i : %d\n", data.i);      data.f = 220.5;   printf( "data.f : %f\n", data.f);      strcpy( data.str, "C Programming");   printf( "data.str : %s\n", data.str);    return 0;}

标题:

  1. 《C 语言共用体:栈上的 "多功能盒子",存新值会覆盖旧值》
  2. 《从内存看共用体:同一块空间,多种解读方式的 "魔术"》

简介:

通过分析共用体代码的内存分配,揭示共用体成员共享同一块内存(大小由最大成员决定)、新值覆盖旧值的特性,解析打印结果混乱的原因,展现共用体节省内存但需注意类型匹配的特点。

关键词:

#C 语言共用体 #栈内存 #内存共享 #类型解析 #内存覆盖

发表评论

泰日号Copyright Your WebSite.Some Rights Reserved. 网站地图 备案号:川ICP备66666666号 Z-BlogPHP强力驱动