温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

C语言栈、堆和静态存储区怎么使用

发布时间:2022-04-18 13:40:27 来源:亿速云 阅读:138 作者:iii 栏目:开发技术

本文小编为大家详细介绍“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语言栈、堆和静态存储区怎么使用”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI