BaysideLizard 发表于 2023-11-26 23:18:10

S1E39:C语言的内存布局--笔记

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

//实验一
int global_uninit_var;
int global_init_var1 = 1;
int global_init_var2 = 2;

int *func(void);

int main()
{
    int local_var1;
    int local_var2;

    static int static_uninit_var;
    static int static_init_var = 3;

    char *str1 = "abc";
    char *str2 = "efg";

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

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

代码段数据段bss段堆栈

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

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

//实验三
    int *ptr1 = NULL;
    int *ptr2 = NULL;

    ptr1 = (int *)malloc(sizeof(int));
    if(ptr1 == NULL)
    {
      exit(1);
    }
    ptr2 = (int *)malloc(sizeof(int));
    if(ptr2 == NULL)
    {
      exit(1);
    }
    printf("\n实验三\n");
    printf("stack:&ptr1-%p | &ptr2-%p\n",&ptr1,&ptr2);
    printf("heap:ptr1-%p | ptr2-%p\n",ptr1,ptr2);

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

    return 0;

}

int *func(void)
{
    int *ptr = NULL;
    ptr = (int *)malloc(sizeof(int));
    if(ptr == NULL)
    {
      exit(1);
    }

    *ptr = 123;

    return ptr;
}








运行结果:
实验一
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天

FishC_GPT 发表于 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官方接口),如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: S1E39:C语言的内存布局--笔记