鱼C论坛

 找回密码
 立即注册
查看: 1143|回复: 1

[作品展示] S1E39:C语言的内存布局--笔记

[复制链接]
发表于 2023-11-26 23:18:10 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. //鱼C论坛——BaysideLizard写于2023年11月26日

  4. //实验一
  5. int global_uninit_var;
  6. int global_init_var1 = 1;
  7. int global_init_var2 = 2;

  8. int *func(void);

  9. int main()
  10. {
  11.     int local_var1;
  12.     int local_var2;

  13.     static int static_uninit_var;
  14.     static int static_init_var = 3;

  15.     char *str1 = "abc";
  16.     char *str2 = "efg";

  17.     int *malloc_var = (int *)malloc(sizeof(int));

  18.     printf("实验一\n");
  19.     printf("addr of func -> %p\n",func);
  20.     printf("addr of str1 -> %p\n",str1);
  21.     printf("addr of str2 -> %p\n",str2);
  22.     printf("addr of global_init_var1 -> %p\n",&global_init_var1);
  23.     printf("addr of global_init_var2 -> %p\n",&global_init_var2);
  24.     printf("addr of static_init_var -> %p\n",&static_init_var);
  25.     printf("addr of static_uninit_var -> %p\n",&static_uninit_var);
  26.     printf("addr of global_uninit_var -> %p\n",&global_uninit_var);
  27.     printf("addr of malloc_var -> %p\n",malloc_var);
  28.     printf("addr of local_var1 -> %p\n",&local_var1);
  29.     printf("addr of local_var2 -> %p\n",&local_var2);
  30. /*C语言的内存布局规律:
  31. 内存地址   低 -------> 高
  32. 函数  字符串常量  全局变量(初始化)  静态变量(初始化)  静态变量(未初始化)  全局变量(未初始化)  动态申请的变量空间  局部变量

  33. 代码段  数据段  bss段  堆  栈

  34. 代码段:存放程序执行代码
  35. 数据段:存放已经初始化的全局变量和局部静态变量
  36. BSS(Block Started by Symbol)段:存放未初始化的全局变量,自动初始化为0
  37. 堆:手动申请与释放
  38. 栈:自动分配与释放
  39. */

  40. //实验二
  41.     int *ptr = NULL;
  42.     ptr = func();
  43.     printf("\n实验二\nptr -> %d\n",*ptr);
  44.     free(ptr);

  45. //实验三
  46.     int *ptr1 = NULL;
  47.     int *ptr2 = NULL;

  48.     ptr1 = (int *)malloc(sizeof(int));
  49.     if(ptr1 == NULL)
  50.     {
  51.         exit(1);
  52.     }
  53.     ptr2 = (int *)malloc(sizeof(int));
  54.     if(ptr2 == NULL)
  55.     {
  56.         exit(1);
  57.     }
  58.     printf("\n实验三\n");
  59.     printf("stack:&ptr1-%p | &ptr2-%p\n",&ptr1,&ptr2);
  60.     printf("heap:ptr1-%p | ptr2-%p\n",ptr1,ptr2);

  61.     ptr1 = realloc(ptr1,2 * sizeof(int));
  62.     printf("realloc ptr1 -> 2 * sizeof(int):%p\n",ptr1);
  63.     ptr1 = realloc(ptr1,20 * sizeof(int));
  64.     printf("realloc ptr1 -> 20 * sizeof(int):%p\n",ptr1);
  65.     //str1的内存地址取决于realloc的大小

  66.     return 0;

  67. }

  68. int *func(void)
  69. {
  70.     int *ptr = NULL;
  71.     ptr = (int *)malloc(sizeof(int));
  72.     if(ptr == NULL)
  73.     {
  74.         exit(1);
  75.     }

  76.     *ptr = 123;

  77.     return ptr;
  78. }
复制代码








运行结果:
实验一
addr of func -> 000000000040177F
addr of str1 -> 0000000000404000
addr of str2 -> 0000000000404004
addr of global_init_var1 -> 0000000000403010
addr of global_init_var2 -> 0000000000403014
addr of static_init_var -> 0000000000403018
addr of static_uninit_var -> 0000000000407030
addr of global_uninit_var -> 0000000000407970
addr of malloc_var -> 0000000000C55E60
addr of local_var1 -> 000000000061FDFC
addr of local_var2 -> 000000000061FDF8

实验二
ptr -> 123

实验三
stack:&ptr1-000000000061FDF0 | &ptr2-000000000061FDE8
heap:ptr1-0000000000C56E90 | ptr2-0000000000C56EB0
realloc ptr1 -> 2 * sizeof(int):0000000000C56E90
realloc ptr1 -> 20 * sizeof(int):0000000000C56ED0

Process returned 0 (0x0)   execution time : 0.037 s
Press any key to continue.








不过我发现了一个问题,在我的电脑上堆的地址似乎更高,这是由于编译器和操作系统的具体实现方式引起的。具体来说,当你运行程序时,操作系统会为进程分配虚拟地址空间,并将其划分为不同的区域,如代码区、数据区(包括全局变量和静态变量)、堆和栈等。
详见https://fishc.com.cn/thread-236996-1-1.html







在FishC学C的第21天
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2023-11-26 23:18:36 | 显示全部楼层
你的代码主要是用来展示C语言的内存布局的。我会逐一解释相关部分。

首先是实验一,你定义了一些全局变量、局部变量、静态变量和动态申请的变量空间,并打印它们的地址。

- 函数`func`的地址是`0x000000000040177F`
- 字符串常量`str1`的地址是`0x0000000000404000`
- 字符串常量`str2`的地址是`0x0000000000404004`
- 全局变量`global_init_var1`的地址是`0x0000000000403010`
- 全局变量`global_init_var2`的地址是`0x0000000000403014`
- 静态变量`static_init_var`的地址是`0x0000000000403018`
- 静态变量`static_uninit_var`的地址是`0x0000000000407030`
- 未初始化的全局变量`global_uninit_var`的地址是`0x0000000000407970`
- 动态申请的变量空间`malloc_var`的地址是`0x0000000000C55E60`
- 局部变量`local_var1`的地址是`0x000000000061FDFC`
- 局部变量`local_var2`的地址是`0x000000000061FDF8`

然后你提到了C语言的内存布局规律,从低地址到高地址,依次是代码段、数据段、BSS段、堆和栈。

- 代码段:存放程序执行代码
- 数据段:存放已经初始化的全局变量和局部静态变量
- BSS段:存放未初始化的全局变量,自动初始化为0
- 堆:手动申请和释放内存
- 栈:自动分配和释放内存

接下来是实验二,你定义了一个指针`ptr`,并将它赋值为`func`函数的返回值,然后打印`ptr`指向的值。

在`func`函数中,你动态申请了一个整型变量的空间,并将其赋值为123,然后返回指向该空间的指针。

运行结果显示`ptr`指向的值是123。

最后是实验三,你首先定义了两个指针`ptr1`和`ptr2`,然后分别对它们进行了动态内存分配,分别打印它们在栈和堆中的地址。

接着使用`realloc`函数重新分配了`ptr1`的内存空间,将原来的大小改为2倍,然后打印`ptr1`的值。接着又将`ptr1`的大小改为20倍,并再次打印`ptr1`的值。

注意,使用`realloc`重新分配内存时,要确保之前申请的指针不为空,否则会出错。

希望以上解释能帮助你理解内存布局和相关概念。如果还有其他问题,请随时提问。

以上回复来自 -- ChatGPT(FishC官方接口),如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-19 23:42

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表