温馨提示×

温馨提示×

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

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

C之程序中的三国天下(三十五)

发布时间:2020-07-20 16:03:28 来源:网络 阅读:558 作者:上帝之子521 栏目:编程语言

        今天我们来探讨下 C 语言中的数据存储方式。在程序中,数据的存储方式无外乎分为栈、堆以及静态存储区。我们分别来看看这三种方式,看看有何区别。

        A、程序中的栈

        栈是现代计算机程序里最为重要的概念之一,栈是用于维护函数调用上下文,同样函数中的参数和局部变量存储在栈上。栈保存了一个函数调用所需的维护信息,如下图所示

C之程序中的三国天下(三十五)

        那么每次函数调用都对应着一个栈上的活动记录:a> 调用函数的活动记录位于栈的中部;b> 被调函数的活动记录位于栈的顶部

C之程序中的三国天下(三十五)

        从 main() 开始运行,我们看到有两个指针 ebp 和 esp。

C之程序中的三国天下(三十五)

        那么当 main() 调用 f() 时,ebp 就往前走四个字节,指向原来 esp 的位置。esp 也继续向前走

C之程序中的三国天下(三十五)

        当从 f() 调用总返回 main() 时,ebp 和 esp 都向回退四个字节。

C之程序中的三国天下(三十五)

        那么我们看到函数调用时,对应的栈空间在函数返回前是专用的。当函数调用后栈空间将被释放,数据不再有效。下图更形象的表示了

C之程序中的三国天下(三十五)

        下来我们以代码为例进行分析

#include <stdio.h>

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

void f()
{
    int* pointer = g();
}

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

        我们看到在函数 g() 中定义了一个数组,但是我们返回了它的地址,也就是返回了局部数组的地址。在 f() 中调用了 g(),这样肯定会出问题,我们来看看编译结果C之程序中的三国天下(三十五)

        我们看到编译器已经给出了警告,那么这么操作肯定是不安全的。

        B、程序中的堆

        那么什么是堆呢?堆是程序中一块预留的内存空间,可由程序自由使用,堆中被程序申请使用的内存在被主动释放前将一直有效。那么我们为什么有了栈还需要堆呢?栈上的数据在函数返回后就会被释放掉,无法传递到函数外部,如:局部数组。那么堆则不一样,如果我们不去主动释放,它就一直有效,但是也就造成了一个问题,如果我们只申请不去释放堆,到最后堆用完了程序便会崩溃。

        那么我们在程序中怎么来申请堆呢?在 C 语言程序中通过库函数的调用来获得堆空间。对应的头文件是 malloc.h;malloc 是以字节的方式动态申请堆空间;free 是将堆空间归还给系统。系统对堆空间的管理方式有这么几种:空闲链表法、位图法以及对象池法等。

        下图是空闲链表管理法的示意图C之程序中的三国天下(三十五)

        如果我们需要申请 4 字节的话,根据这个表来看,我们便会申请到跟它最匹配的,便是 5 字节了。所以有时我们申请的空间会比我们所需的大一点。

        C、程序中的静态存储区

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

        下来我们以代码为例来进行分析

#include <stdio.h>

int g_v = 1;

static int g_vs  = 2;

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

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

        我们看到分别定义了三个变量,第3行是 int 型的全局变量,第5行是加 static 修饰的 int 型变量,第9行是加 static 修饰的函数内的局部变量。我们分别来打印下三个变量的地址,看看他们有什么关系

C之程序中的三国天下(三十五)

        那么我们看到虽然他们三个类型不同,但是地址是连续的,也就证明他们三个是分布在同一个数据区的,便是静态存储区啦。通过本节对栈、堆以及静态存储区的学习,总结如下:1、栈区主要用于函数调用的使用;2、堆区主要是用于内存的动态申请和归还;3、静态存储区用于保存全局变量和静态变量。


        欢迎大家一起来学习 C 语言,可以加我QQ:243343083

向AI问一下细节

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

AI