第39课 程序中的三国天下

1. 程序中的栈

1.1 栈的简介

(1)栈中现代计算机程序里最为重要的概念之一

(2)栈在程序中用于维护函数调用上下文

(3)函数中的参数局部变量存储在栈上

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

1.2 函数调用过程

(1)每次函数调用都对应着一个栈上的活动记录,调用函数的活动记录位于栈的中部被调用函数的活动记录位于栈的顶部

(2)函数调用栈的变化:以int main(){f();}→f(){}为例

1.3 函数调用栈上的数据

(1)函数调用时,对应的栈空间在函数返回前是专用的

(2)函数调用结束后,栈空间将被释放,数据不再有效

【编程实验】指向栈数据的指针

#include <stdio.h>

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

    return a; //返回栈中的数组
}

void f()
{
    int i = 0;
    int array[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

    int* pointer = g();//pointer指向g函数栈中的数组

    /*
    //当g函数返回后,马上将栈中的数组保存到array中
    //但如果有其他函数的调用,则pointer所指向栈中的数组数据将是无效的!
    for (int i = 0; i < 10;i++)
    {
        array[i] = pointer[i];
    }

    for (i = 0; i < 10;i++){
        printf("array[%d] = %d\n", i, array[i]);
    }
    */
}

int main()
{
    f();

    return 0;
}

2. 程序中的堆

(1)堆是程序中一块预留的内存空间,可由程序自由使用

(2)堆中被程序申请使用的内存在被主动释放前将一直有效

(3)为什么有了栈还需要堆?(栈上的数据在函数返回后就会被释放掉,无法传递到函数外部,如局部数组)

(4)C语言中通过库函数的调用获得堆空间:malloc和free

(5)系统对堆空间的管理方式(空闲链表法、位图法、对象池法等等)

3. 程序中的静态存储区

(1)静态存储区随着程序的运行而分配空间

(2)静态存储区的生命周期直到程序运行结束

(3)在程序的编译期静态存储区的大小就己经确定

(4)静态存储区主要用于保存全局变量静态局部变量

(5)静态存储区的信息最终会保存到可执行程序中

【编程实验】静态存储区的验证

#include <stdio.h>

int g_v = 1;     //静态区
static int g_vs; //静态区,只有本文件可见

void f()
{
    static int g_v1 = 3; //局部静态变量——静态区
    printf("g_v1 = %p\n", &g_v1);
}

int main()
{
    printf("g_v = %p\n", &g_v);     //g_v、g_vs、g_v1三者地址比较相邻
    printf("g_vs = %p\n", &g_vs);

    f();

    return 0;
}

4. 小结:三个基本数据区

(1)栈区主要用于函数调用的使用

(2)堆区主要用于内存的动态申请和归还

(3)静态存储区用于保存全局变量静态变量

时间: 2024-10-29 17:44:30

第39课 程序中的三国天下的相关文章

第39课 Qt中的事件处理(下)

1. 事件的传递过程 (1)操作系统检测到用户动作时,会产生一条系统消息,该消息被发送到Qt应用程序 (2)Qt应用程序收到系统消息后,将其转化为一个对应的事件对象,并将其分发出去. (3)事件对应被分发到当前正在操作的窗口部件上,该窗口部件会调用event函数来处理,然后,在这个函数内部又会调用其他的子函数(如KeyPress或mouseReleaseEvent)来进行具体的处理. (4)event函数处理完后,可能会将当前事件传递给父组件(parent)对象.但这个过程只是一种可能,也就是有

第51课 程序中的配置文件

1. 程序状态的保存和恢复 (1)程序的状态 ①应用程序在运行后都有一个初始化的状态 ②一般而言,程序的初始状态是最近一次运行退出前的状态 (2)解决思路 ①程序退出前保存状态参数到文件(数据库) ②程序再次启动时读出状态参数并恢复 (3)状态参数的存储方式 ①文本文件格式(XML.JSon等) ②轻量级数据库(Access.SQLite等) ③私有二进制文件格式 2. Qt中的解决方案 (1)通过二进制数据流将状态参数直接存储于文件中 (2)优势 ①参数的存储和读取简单高效,易于编码实现 ②最

第7课 - 程序中的数据输入

1.问题:如何使用C语言从键盘输入数据? stdio.h工具包提供了一个数据输入工具scanf scanf通过正确设置后,能够获取键盘输入的数据 scanf将键盘获取的数据“填入”变量 stdio.h中scanf的使用示例: 注意事项: scanf中的格式化字符不能包含其他无关字符 scanf中的格式化字符必须与对应的变量类型一致 编程实验:键盘输入 7-1.c 2.编程小任务:输入两个整数,并求和 思路: 定义2个用于相加的整型变量 使用scanf从键盘输入整数 使用printf打印相加的结果

Spark3000门徒第9课IDEA中开发Spark实战总结

今晚听了王家林老师的第9课IDEA中开发Spark实战,课后作业是:在Idea中编写广告点击排名的程序并提交集群测试, IDEA社区版本就够用,Ultimate没必要还要钱 程序如下: object WordCountCluster { def main(args: Array[String]){ /** * 第一步:创建spark的配置对象SparkConf,设置Spark程序的运行时的配置信息 * */ val conf = new SparkConf() //创建SparkConf对象 c

关于iOS程序中插入广告的问题

版权所有,转载请注明出处 陈军刚 对于开发面向全球用户的免费软件,插入Google的Admob广告和Apple的iAd是开发者实现盈利的最好选择.那接下来将介绍一些在iOS程序中插入Google的Admob广告的一些步骤. 第一步:加入ADBannerView 首先,在你的工程中引入iAd.framework ScenicViewController.h 1 #import <UIKit/UIKit.h> 2 #import <iAd/iAd.h> 3 4 @interface S

在.net桌面程序中自定义鼠标光标

有的时候,一个自定义的鼠标光标能给你的程序增色不少.本文这里介绍一下如何在.net桌面程序中自定义鼠标光标.由于.net的桌面程序分为WinForm和WPF两种,这里分别介绍一下. WinForm程序 对于WinForm程序,可以通过修改Control.Cursor属性来实现光标的修改,如果我们有光标文件的话,可以直接通过如下代码实现自定义光标: this.Cursor = new Cursor("myCursor.cur"); 但这种方式不是本文介绍的重点,本文主要介绍如何自己绘制光

Native Application 开发详解(直接在程序中调用 ntdll.dll 中的 Native API,有内存小、速度快、安全、API丰富等8大优点)

文章目录:                   1. 引子: 2. Native Application Demo 展示: 3. Native Application 简介: 4. Native Application 有何妙用: 5. MJ0011 关于 Native Application 的文章整理: 6. 互联网上其他关于 Native Application 的文章整理: 7. 小结: 1. 引子: 其实在好久以前就看了 MJ0011 翻译的那个<Native 应用程序详细>系列的文

linux c程序中获取shell脚本输出的实现方法

linux c程序中获取shell脚本输出的实现方法 1. 前言Unix界有一句名言:“一行shell脚本胜过万行C程序”,虽然这句话有些夸张,但不可否认的是,借助脚本确实能够极大的简化一些编程工作.比如实现一个ping程序来测试网络的连通性,实现ping函数需要写上200~300行代码,为什么不能直接调用系统的ping命令呢?通常在程序中通过 system函数来调用shell命令.但是,system函数仅返回命令是否执行成功,而我们可能需要获得shell命令在控制台上输出的结果.例如,执行外部

Spark3000门徒第8课IDE中开发Spark实战总结

今晚听了王家林老师的第8课IDE中开发Spark实战,课后作业是:在Eclipse中编写广告点击排名的程序并测试,程序如下: object WordCountCluster { def main(args: Array[String]){ /** * 第一步:创建spark的配置对象SparkConf,设置Spark程序的运行时的配置信息 */ val conf = new SparkConf() //创建SparkConf对象 conf.setAppName("First App")