#include<stdio.h>
#include<stdlib.h>
int global_uninit_var; //全局未初始化变量
int global_init_var1=1; //全局初始化变量
int global_init_var2=2; //全局初始化变量
int static_global_uninit_var; //静态全局变量(未初始化)
int static_global_init_var=3; //静态全局变量(初始化)
void func(void);
void func(void)
{
;
}
int main(int argc,char** argv)
{
int local_init_var=1; //局部变量初始化
int local_var1; //局部变量1
int local_var2; //局部变量2
static int static_local_uninit_var; //静态局部未初始化变量
static int static_local_init_var=10; //静态局部初始化变量
char* str1="hello"; //字符串常量1
char* str2="world"; //字符串常量2
int* malloc_var=(int*)malloc(sizeof(int)); //动态申请内存
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_global_init_var -> %p\n", &static_global_init_var);
printf("addr of static_local_init_var -> %p\n", &static_local_init_var);
printf("addr of static_local_uninit_var -> %p\n", &static_local_uninit_var);
printf("addr of global_uninit_var -> %p\n", &global_uninit_var);
printf("addr of static_global_uninit_var -> %p\n", &static_global_uninit_var);
printf("addr of malloc_var -> %p\n", malloc_var);
printf("addr of local_init_var -> %p\n", &local_init_var);
printf("addr of local_var1 -> %p\n", &local_var1);
printf("addr of local_var2 -> %p\n", &local_var2);
/*
以下各个地址从小到大排列
addr of func -> 0x55bfc58bf189 //函数
addr of str1 -> 0x55bfc58c0008
addr of str2 -> 0x55bfc58c000e //字符串常量
addr of global_init_var1 -> 0x55bfc58c2010
addr of global_init_var2 -> 0x55bfc58c2014 //全局变量(初始化)
addr of static_global_init_var -> 0x55bfc58c2018 //静态全部变量(初始化)
addr of static_local_init_var -> 0x55bfc58c201c //静态局部变量(初始化)
addr of static_local_uninit_var -> 0x55bfc58c2024 //静态局部变量(未初始化)
addr of global_uninit_var -> 0x55bfc58c2028 //全局变量(未初始化)
addr of static_global_uninit_var -> 0x55bfc58c202c //静态全局变量(未初始化)
addr of malloc_var -> 0x55bfc70402a0 //动态申请的内存空间
addr of local_init_var -> 0x7fff1fc55044 //局部变量(初始化)
addr of local_var1 -> 0x7fff1fc55048 //局部变量(未初始化)
addr of local_var2 -> 0x7fff1fc5504c
*/
return 0;
}
C语言内存布局规律
内存布局
代码段
存放程序执行代码,这部分区域大小在程序运行前就已经确定,并且通常为只读权限,也有可能包含一些只读变量,如字符串常量等。
数据段
通常用来存放已经初始化的全局变量和局部静态变量
BSS(Block Started by Symbol)段
通常用来存放程序中未初始化的全局变量和局部静态变量,这个区段中的数据在程序运行前被自动初始化为0
在linux系统下编辑以下代码test.c
#include<stdio.h>
int main(int argc,char** argv)
{
return 0;
}
使用以下命令编译生成test可执行文件
gcc test.c -o test
使用以下命令查看test所占内存情况
size test
size test
text为占用代码段大小,data为占用数据段大小,bss为占用BSS段内存大小
在代码中添加一个初始化的全局变量
#include<stdio.h>
int global_uninit_var=1;
int main(int argc,char** argv)
{
return 0;
}
再次使用上面的命令重新编译执行并size test查看大小
size test
数据段为548个字节,多了4个字节,但为什么BSS少了四个字节?(求大神告知),证明初始化的全局变量存储于数据段,要验证其他变量存储区域,采用同样的方法。
堆
存放进程运行中被动态分配的内存段,大小不固定,可动态扩展或缩小。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上,当利用free等函数释放内存时,被释放的内存从堆中被剔除。
栈
栈时函数执行的内存区域,通常和堆共享同一片区域,如函数的参数、返回值都是放在栈里的。
堆和栈的区别
1.申请和释放方式
堆由程序员手动申请,手动释放
栈由系统自动分配,自动释放
2.生存周期
堆的声明周期由动态申请到程序员主动释放为止,不同函数之间可以自由访问
#include <stdio.h>
#include<stdlib.h>
int* func(void)
{
int* ptr = NULL;
ptr = (int*)malloc(sizeof(int));
if (ptr == NULL)
{
printf("申请失败\n");
}
else
{
*ptr = 1;
}
return ptr;
}
int main(int argc, char** argv)
{
int* ptr = NULL;
ptr = func();
printf("%d\n", *ptr); //1 main函数可以访问到func函数中在堆中申请的内存,不建议,最好在哪个函数申请,就在那个函数释放
free(ptr);
return 0;
}
栈的生存周期由函数调用到函数返回时结束,函数之间的局部变量存在于栈上,不可互相访问
3.发展方向(不同的编译器和机器有可能不一样):
堆和其他区段都是从低地址向高地址发展
栈则相反,从高地址向低地址发展















网友评论