C之数据存储方式(三十五)

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

A、程序中的栈

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

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

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

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

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

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

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

#include <stdio.h>

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

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

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

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

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

B、程序中的堆

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

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

下图是空闲链表管理法的示意图

如果我们需要申请 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 修饰的函数内的局部变量。我们分别来打印下三个变量的地址,看看他们有什么关系

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

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

原文地址:http://blog.51cto.com/12810168/2107905

时间: 2024-11-10 13:40:07

C之数据存储方式(三十五)的相关文章

android五种数据存储方式

在Android中提供了如下五种数据存储方式: SharedPreferences 文件存储 SQLite数据库方式 内容提供器(ContentProvider) 网络存储 下面具体介绍一下这五种数据存储方式的用法. 1. SharedPreferences SharedPreferences是android平台上的一个轻量级存储类,主要保存一些常用的配置信息.可以保存long.int.String类型数据. SharedPreferences以键值对方式读取和存入,最终会以XML方式保存数据,

NeHe OpenGL教程 第三十五课:播放AVI

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第三十五课:播放AVI 在OpenGL中播放AVI: 在OpenGL中如何播放AVI呢?利用Windows的API把每一帧作为纹理绑定到OpenGL中,虽然很慢,但它的效果不错.你可以试试. 首先我得说我非常喜欢这一章节.Jonat

Python进阶(三十五)-Fiddler命令行和HTTP断点调试

Python进阶(三十五)-Fiddler命令行和HTTP断点调试 一. Fiddler内置命令 ??上一节(使用Fiddler进行抓包分析)中,介绍到,在web session(与我们通常所说的session不是同一个概念,这里的每条HTTP请求都称为一个session).界面中能够看到Fiddler抓取的全部HTTP请求.而为了更加方便的管理全部的session, Fiddler提供了一系列内置的函数用于筛选和操作这些session(习惯命令行操作Linux的童鞋应该能够感受到这会有多么方便

iOS开发UI篇—ios应用数据存储方式(XML属性列表-plist)

一.ios应用常用的数据存储方式 1.plist(XML属性列表归档) 2.偏好设置 3.NSKeydeArchiver归档(存储自定义对象) 4.SQLite3(数据库,关系型数据库,不能直接存储对象,要编写一些数据库的语句,将对象拆开存储) 5.Core Data(对象型的数据库,把内部环节屏蔽) 二.应用沙盒 每个iOS应用都有?己的应?沙盒(应用沙盒就是文件系统目录),与其他文件系统隔离.应?必须待在?己的沙盒里,其他应用不能访问该沙盒(提示:在IOS8中已经开放访问) 应?沙盒的文件系

android的数据存储方式

数据存储在开发中是使用最频繁的,Android平台中实现数据存储主要有5种方式,分别是: 1 SQLite: SQLite是一个轻量级嵌入式数据库,支持基本SQL语法,是常被采用的一种数据存储方式.Android为此数据库提供了一个名为SQLiteDatabase的类,封装了一些操作数据库的API. 2 SharedPreference:SharedPreferences也是一种轻型的数据存储方式,它的本质是基于XML文件存储key-value键值对数据,通常用来存储一些简单的配置信息.其存储位

iOS狂暴之路---iOS中应用的数据存储方式解析

一.前言 前面一篇文章中已经介绍了iOS应用中的视图控制器知识点,而本文不会按照常理来介绍View的知识点,而是先介绍iOS中的数据存储知识点,因为关于View的知识点太多了,后面会连续详细介绍一下.这篇先来看一下iOS中的数据存储功能分析.每一个iOS应用和Android应用一样,都有其对应的沙盒存储自己的数据,但是iOS和Android有一个区别就在于没有SD卡的概念了,也就说在iOS中应用的数据只能保存到自己的沙盒中.这也可以看出来iOS为了应用的安全考虑. 在开发Android的时候都知

转 数据存储方式

总体的来讲,数据存储方式有三种:一个是文件,一个是数据库,另一个则是网络.其中文件和数据库可能用的稍多一些,文件用起来较为方便,程序可以自己定义格式:数据库用起稍烦锁一些,但它有它的优点,比如在海量数据时性能优越,有查询功能,可以加密,可以加锁,可以跨应用,跨平台等等:网络,则用于比较重要的事情,比如科研,勘探,航空等实时采集到的数据需要马上通过网络传输到数据处理中心进行存储并进行处理. 对于Android平台来讲,它的存储方式也不外乎这几种,按方式总体来分,也是文件,数据库和网络.但从开发者的

iOS 应用数据存储方式(XML属性列表-plist)

iOS 应用数据存储方式(XML属性列表-plist) 一.ios应用常用的数据存储方式 1.plist(XML属性列表归档) 2.偏好设置 3.NSKeydeArchiver归档(存储自定义对象) 4.SQLite3(数据库,关系型数据库,不能直接存储对象,要编写一些数据库的语句,将对象拆开存储) 5.Core Data(对象型的数据库,把内部环节屏蔽) 二.应用沙盒 每个iOS应用都有?己的应?沙盒(应用沙盒就是文件系统目录),与其他文件系统隔离.应?必须待在?己的沙盒里,其他应用不能访问该

Gradle 1.12用户指南翻译——第三十五章. Sonar 插件

本文由CSDN博客万一博主翻译,其他章节的翻译请参见: http://blog.csdn.net/column/details/gradle-translation.html 翻译项目请关注Github上的地址: https://github.com/msdx/gradledoc/tree/1.12. 直接浏览双语版的文档请访问: http://gradledoc.qiniudn.com/1.12/userguide/userguide.html. 另外,Android 手机用户可通过我写的一个