服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C语言深入讲解栈与堆和静态存储区的使用

C语言深入讲解栈与堆和静态存储区的使用

2022-11-10 15:02清风自在 流水潺潺 C/C++

对大多数C 语言初学者来说,堆栈却是一个很模糊的概念。堆栈是一种数据结构,一个在程序运行时用于存放的地方,相信这可能是很多初学者共同的认识,静态存储区即内存在程序编译的时候就已经分配好,这块内存在程序的整个

一、程序中的

  • 栈是现代计算机程序里最为重要的概念之一
  • 栈在程序中用于维护函数调用上下文
  • 函数中的参数和局部变量存储在栈上

C语言深入讲解栈与堆和静态存储区的使用

栈保存了一个函数调用所需的维护信息

  • 参数
  • 返回地址
  • 局部变量
  • 调用上下文

C语言深入讲解栈与堆和静态存储区的使用

 

二、函数的调用过程

每次函数调用都对应着一个栈上的活动记录

  • 调用函数的活动记录位于栈的中部
  • 被调函数的活动记录位于栈的顶部

C语言深入讲解栈与堆和静态存储区的使用

 

三、函数调用的栈变化

从main() 开始运行

C语言深入讲解栈与堆和静态存储区的使用

main() 调用 f()

C语言深入讲解栈与堆和静态存储区的使用

当从 f() 调用中返回 main()

C语言深入讲解栈与堆和静态存储区的使用

 

四、函数调用栈上的数据

  • 函数调用时,对应的栈空间在函数返回前是专用的
  • 函数调用结束后,栈空间将被释放,数据不再有效

C语言深入讲解栈与堆和静态存储区的使用

下面看一个指向栈数据的指针:

#include <stdio.h>

int* g()
{
  int a[10] = {0};
  return a;
}

void f()
{
  int i = 0;
  int b[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
  int *pointer = g();
  
  for (i = 0; i < 10; i++)
  {
      b[i] = pointer[i];
  }
  for(i = 0; i < 10; i++)
  {
      printf("%d\n", b[i]);
  } 
}

int main()
{
  f();
  return 0;
}

输出结果如下:

C语言深入讲解栈与堆和静态存储区的使用

如果把

for (i = 0; i < 10; i++)

{

b[i] = pointer[i];

}

注释了,直接打印 pointer[i] 里面的数据,如下:

#include <stdio.h>

int* g()
{
  int a[10] = {0};
  return a;
}

void f()
{
  int i = 0;
  int b[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
  int *pointer = g();
  /*
  for (i = 0; i < 10; i++)
  {
      b[i] = pointer[i];
  }
  */
  for(i = 0; i < 10; i++)
  {
      printf("%d\n", pointer[i]);
  } 
}

int main()
{
  f();
  return 0;
}

输出结果如下:

C语言深入讲解栈与堆和静态存储区的使用

为什么直接打印 pointer[i] 里面的值会是这样呢?因为 pointer 指向的空间是栈空间,栈空间在 g() 函数返回之后,活动记录就被释放了。被释放后调用 printf 函数,printf 函数需要在栈上面建立一个活动记录。这个活动记录就会有 printf 函数的参数信息和返回值等,所以 pointer 所指向的内存里面的数据由于 printf 函数的调用被改变了。因此,不能返回局部变量的地址,不能返回局部数组的数组名。

 

五、程序中的

  • 堆是程序中一块预留的内存空间,可由程序自由使用
  • 堆中被程序申请使用的内存在被主动释放前将一直有效

为什么有了栈还需要堆?

答:栈上的数据在函数返回后就会被释放掉,无法传递到函数外部,如:局部数组

C语言程序中通过库函数的调用获得堆空间

  • 头文件:malloc.h
  • malloc -- 以字节的方式动态申请堆空间
  • free -- 将堆空间归还给系统

系统对堆空间的管理方式

空闲链表法,位图法,对象池法等等

C语言深入讲解栈与堆和静态存储区的使用

以int* p = (int*)malloc(sizeof(int)); 为例,要申请 4 个字节的大小,遍历之后发现跟 5 Bytes 这个节点最接近,找到一个可以用的单元之后,就将这个单元的地址返还给了 p 指针。以前也提过使用 malloc 申请内存空间时返回的内存空间可能比申请的实际内存空间要大一点点,原因就是在空闲链表管理堆空间这样的系统里面,它会找最近的那个,找到后的一般都大于等于所需要的内存空间,假如5 Bytes 这个节点下所有的空闲内存单元都用完的话,就会找12 Bytes 节点下的内存单元,这样malloc 返回的内存空间就有可能比自己实际申请的内存空间要大。

 

六、程序中的静态存储区

  • 静态存储区随着程序的运行而分配空间
  • 静态存储区的生命周期直到程序运行结束
  • 在程序的编译期静态存储区的大小就已经确定
  • 静态存储区主要用于保存全局变量和静态局部变量
  • 静态存储区的信息最终会保存到可执行程序中

下面看一个静态存储区的验证代码:

#include <stdio.h>

int g_v = 1;

static int g_vs  = 2;

void f()
{
  static int g_vl = 3;
  
  printf("%p\n", &g_vl);
}

int main()
{
  printf("%p\n", &g_v);
  
  printf("%p\n", &g_vs);
  
  f();
  
  return 0;
}

输出结果如下:

C语言深入讲解栈与堆和静态存储区的使用

可以看到这三个地址是顺序存放的,因为这三个变量都是存放在程序的静态存储区,静态存储区在程序里面有固定的起始地址。

 

七、小结

栈,堆和静态存储区是程序中的三个基本数据区

  • 栈区主要用于函数调用的使用
  • 堆区主要是用于内存的动态申请和归还
  • 静态存储区用于保存全局变量和静态变量

到此这篇关于C语言深入讲解栈与堆和静态存储区的使用的文章就介绍到这了,更多相关C语言 栈与堆内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/weixin_43129713/article/details/124093704

延伸 · 阅读

精彩推荐
  • C/C++基于Opencv实现双目摄像头拍照程序

    基于Opencv实现双目摄像头拍照程序

    这篇文章主要为大家详细介绍了基于Opencv实现双目摄像头拍照程序,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    sk_sk11592021-07-28
  • C/C++C++ 类中有虚函数(虚函数表)时 内存分布详解

    C++ 类中有虚函数(虚函数表)时 内存分布详解

    下面小编就为大家带来一篇C++ 类中有虚函数(虚函数表)时 内存分布详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看...

    C++教程网6872021-04-24
  • C/C++深入了解C语言中的const和指针

    深入了解C语言中的const和指针

    这篇文章将具体为大家介绍一下C语言中const和指针的使用,文中的示例代码讲解详细,对我们学习const和指针有一定帮助,需要的可以参考一下...

    叫我小秦就好了5622022-09-24
  • C/C++编写C语言程序进行进制转换的问题实例

    编写C语言程序进行进制转换的问题实例

    这篇文章主要介绍了编写C语言程序进行进制转换的问题实例,文中附录了一个各种进制间的转换程序代码,需要的朋友可以参考下...

    低调小一10662021-03-06
  • C/C++C 字符串数组排序的小例子

    C 字符串数组排序的小例子

    C 字符串数组排序的小例子,需要的朋友可以参考一下...

    C语言教程网1842020-11-19
  • C/C++C++中可以接受任意多个参数的函数定义方法(详解)

    C++中可以接受任意多个参数的函数定义方法(详解)

    下面小编就为大家带来一篇C++中可以接受任意多个参数的函数定义方法(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编...

    C++教程网11252021-04-19
  • C/C++详解C语言初阶之数组

    详解C语言初阶之数组

    这篇文章主要介绍了C语言中的数组基础,介绍了其相关概念,具有一定参考价值。需要的朋友可以了解下,希望能够给你带来帮助...

    鲸落之·海3632022-02-22
  • C/C++C++实现图书管理系统课程设计

    C++实现图书管理系统课程设计

    这篇文章主要为大家详细介绍了C++实现图书管理系统课程设计,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    RooKiChen9722022-10-18