【C语言】-- 一篇带你了解C语言内存五大区——栈区,堆区,全局区,常量区,代码区

马肤
这是懒羊羊

目录

1 C语言的内存分区

1.1 内存五大分区

1.2 内存分区简介

1.2.1 栈区(stack)

1.2.2 堆区(heap)

1.2.3 (全局)静态区

1.2.4 常量区

1.2.5 代码区

创作不易,如果本篇博客对您有一定的帮助,大家记得留言+点赞哦。


C语言已经持续学习一段时间了,今天特此总结一下关于C语言内存的五大区。它是我们深入理解C语言非常有必要了解的知识点。通过了解五大区,对于进一步学习C语言底层是非常有帮助的。

1 C语言的内存分区

1.1 内存五大分区

C语言内存可大致分为5个区域,图和表如下:

内存影像区内容 权限
栈区函数中的普通变量可读可写
堆区动态申请的内存可读可写
(全局)静态变量区static修饰的变量可读可写
常量区用于初始化变量的常量只读
代码区代码指令只读

nt k=1;
void main()
{
	int i=1;
	char *j;
	static int m=1;
	char *n="hello";
 
	printf("栈区地址为:0X%x\n",&i);		
	j = (char*)malloc(2); //一般不确定需要多大空间的时候用
	free(j);//及时释放
	printf("堆区地址为:0X%x\n",j);
	printf("全局变量地址为:0X%x\n",&k);
	printf("静态变量地址为:0X%x\n",&m);
	printf("文字常量区地址为:0X%x\n",n);
	printf("程序区地址为:0X%x\n",&main);
}
 
	char *i="hello";
	char j[10]="hello";
	printf("0X%x\n",i); //存放在文字常量区
	printf("0X%x\n",j); //存放在栈区
	j[1]='*';//可以直接赋值
	//*(i+1)='*'; //等价于i[1]='*';
	//不可以这样赋值, 因为i是指针,指向的是文字常量区,里面的内容是不能修改的
	i=j; //这样可以
	printf("%s\n",i);
	printf("%x\n",i);
	j=i;//这样不可以,因为j虽然也是地址,但是不是指针变量,不能直接赋值

1.2 内存分区简介

1.2.1 栈区(stack)

栈区由编译器自动分配释放,由操作系统自动管理,无须手动管理。

栈区上的内容只在函数范围内存在,当函数运行结束,这些内容也会自动被销毁。

#include
char *getMem()
{
	char buf[64]; //局部变量 栈区存放
	strcpy(buf, "123456789");//向buf所代表的内存中写入内容
	//printf("buf:%s\n", buf);
	return buf;//返回所分配内存区域的第一个元素的地址
}
 
void main()
{
	char *tmp = NULL;
	tmp = getMem(10);
	if (tmp == NULL)
	{
		return ;
	}
	printf("tmp:%s\n", tmp);//输出tmp:
	system("pause");
	return ;
}

内存分析:

      【C语言】-- 一篇带你了解C语言内存五大区——栈区,堆区,全局区,常量区,代码区,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,操作,程序,进行,第2张

 

  • 栈区按内存地址由高到低方向生长,其最大大小由编译时确定,速度快,但自由性差,最大空间不大。
  • 栈区是先进后出原则,即先进去的被堵在屋里的最里面,后进去的在门口,释放的时候门口的先出去。
  • 栈区存放内容

  • 临时创建的局部变量和const定义的局部变量存放在栈区。
  • 函数调用和返回时,其入口参数和返回值存放在栈区。

    通俗来说:

    栈区是用来存放局部变量的,比如函数内部定义的int a,int b,const int a,char p,char arr[ ],还有函数的形参等等都是存放在栈区。栈区的数据由编译器管理,调用完之后就自动释放,压栈,出栈。先进后出的原则,比如当你执行到函数调用的时候,编译器会先把下一条代码的地址压入栈中,再把你调用的那个函数里的一些局部变量啊,形参啊等等压入栈中,等你函数调用执行完毕。栈就会把你调用的这个函数之前压入栈的变量和形参全部清除出栈,之后根据下一条代码的地址,接着执行程序,以后的程序也都是这么执行。栈区是有大小的,一般是1M左右,所以别定义太大的数组。

     

    1.2.2 堆区(heap)

    堆区由程序员分配内存和释放。若程序员不释放,程序结束时可能由操作系统回收。

    #include 
    char *getMem(int num)
    {
    	char *p1 = NULL;
    	p1 = (char *)malloc(sizeof(char) * num);
    	if (p1 == NULL)
    	{
    		return NULL;
    	}
    	return p1;
    }
    void main()
    {
    	char *tmp = NULL;
    	tmp = getMem(10);
    	if (tmp == NULL)
    	{
    		return ;
    	}
    	strcpy(tmp, "111222"); //向tmp做指向的内存空间中copy数据,注意不是向指针变量tmp中
    	printf("tmp:%s\n", tmp);//输出tmp:111222
    	system("pause");
    	return ;
    }

    内存分析:

            【C语言】-- 一篇带你了解C语言内存五大区——栈区,堆区,全局区,常量区,代码区,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,操作,程序,进行,第3张

     

    • 堆区按内存地址由低到高方向生长,其大小由系统内存/虚拟内存上限决定,速度较慢,但自由性大,可用空间大。

      堆区动态申请与释放内存

      用malloc(),free()等函数实现动态分布内存。

      void *malloc(size_t);
      
      • 参数size_t是分配的字节大小;
      • 返回值是一个void*型的指针,该指针指向分配空间的首地址;

        (void *型指针可以任意转换为其他类型的指针)

        用free()函数进行内存释放,否则会造成内存泄漏。

        void free(void * /*ptr*/);
        
        • 参数ptr是开辟的内存的首地址。
        • 无返回值;

          通俗来说:

          由程序员手动申请和释放

          比如:int p=(int )malloc(sizeof(int)10),表示申请了一块40个字节的堆区空间,然后申请完记得用free释放。

          代码区的话就是用来存放代码的,转化为二进制存放。

          1.2.3 (全局)静态区

          通常是用于那些在编译期间就能确定存储大小的变量的存储区,但它用于的是在整个程序运行期间都可见的全局变量和静态变量。

          全局区有 .bss段 和 .data段组成,可读可写。

          #include 
          char * getStr1()
          {
          	char *p1 = "abcd";
          	return p1;
          }
          char *getStr2()
          {
          	char *p2 = "abcd";
          	return p2;
          }
           
          void main()
          {
          	char *p1 = NULL;
          	char *p2 = NULL;
          	p1 = getStr1();
          	p2 = getStr2();
           
          	//打印p1 p2 所指向内存空间的数据,不是p1 p2中的数据
          	printf("p1:%s , p2:%s \n", p1, p2);//输出p1:abcd , p2:abcd
           
          	//打印p1 p2 的值
          	printf("p1:%d , p2:%d \n", p1, p2);//输出p1:19184372 , p2:19184372
           
          	system("pause");
          	return;
          }

          内存分析:

                   【C语言】-- 一篇带你了解C语言内存五大区——栈区,堆区,全局区,常量区,代码区,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,操作,程序,进行,第4张

           

          • .bss段

            未初始化的全局变量和未初始化的静态变量存放在.bss段。

            初始化为0的全局变量和初始化为0的静态变量存放在.bss段。

            .bss段不占用可执行文件空间,其内容由操作系统初始化。

          • .data段

            已初始化的全局变量存放在.data段。

            已初始化的静态变量存放在.data段。

            .data段占用可执行文件空间,其内容有程序初始化。

            通俗来说:

            全局区比较特殊,里面还分成了全局变量区,静态变量区,常量区。全局变量区用来存放全局变量,静态变量区用来存放带有static修饰的变量(包括静态局部变量和静态全局变量),只要含有static就存在这个区。常量区是用来存放字符常量的,还有const修饰的全局变量的,const 修饰的局部变量不存在这里,别搞混了。全局区存放的一切都是由操作系统管理,等程序结束由操作系统释放。常量区里存放的数据不可更改,就算你用指针也不行,你可能会说const修饰的局部变量都可以用指针改,但是局部变量可不是存放在常量区,这点搞清楚。

            1.2.4 常量区

            字符串、数字等常量存放在常量区。
            const修饰的全局变量存放在常量区。

            程序运行期间,常量区的内容不可以被修改。

            1.2.5 代码区

            程序执行代码存放在代码区,其值不能修改(若修改则会出现错误)。
            字符串常量和define定义的常量也有可能存放在代码区。

                    以上五区,代码区和全局区是在生成.exe文件之后就有了,双击.exe文件运行程序才会生成栈区和堆区。

            下面直接上图:

            #include
            #include
            int a = 10;
            static int b = 20;
            void fun(int x)
            {
            	char *p = "Hello";
            	printf("形参x的地址=%d\n\n", &x);
            	printf("Hello的地址=%d\n\n", "Hello");
            	printf("指针变量p的地址=%d\n\n", &p);
            	return;
            }
            int main(int argc,const char *argv[])
            {
            	int c = 10;
            	int d = 20;
            	static int e = 30;
            	char *p = "Hello";
            	printf("\n全局变量a的地址=%d\n\n", &a);
            	printf("静态全局变量b的地址=%d\n\n", &b);
            	printf("静态局部变量e的地址=%d\n\n", &e);
            	printf("字符串\"Hello\"的地址=%d\n\n", "Hello");
            	printf("局部变量c的地址=%d\n\n", &c);
            	printf("局部变量d的地址=%d\n\n", &d);
            	printf("指针变量p的地址=%d\n\n", &p);
            	fun(5);
            	system("pause");
            	return 0;
            }
            

            【C语言】-- 一篇带你了解C语言内存五大区——栈区,堆区,全局区,常量区,代码区,词库加载错误:未能找到文件“C:\Users\Administrator\Desktop\火车头9.8破解版\Configuration\Dict_Stopwords.txt”。,操作,程序,进行,第6张

             简单的用图表示了一下,总结:

            全局区存放的是全局变量,静态变量,字符常量,const 修饰的全局变量。栈区存放的是局部变量和函数的形参,以及一些代码的地址,栈区的内容是可以修改的

            堆区是由程序员手动申请和释放,用malloc函数申请,用free函数释放。

            创作不易,如果本篇博客对您有一定的帮助,大家记得留言+点赞哦。


文章版权声明:除非注明,否则均为VPS857原创文章,转载或复制请以超链接形式并注明出处。

发表评论

快捷回复:表情:
评论列表 (暂无评论,0人围观)

还没有评论,来说两句吧...

目录[+]

取消
微信二维码
微信二维码
支付宝二维码