第 12 章 存储类别、链接和内存管理

一、作用域

1.1 块作用域

定义在块内的变量具有块作用域,块是用一对花括号括起来的代码区域。

1.2 函数作用域

函数作用域仅用于 goto 语句的标签。

1.3 函数原型作用域

函数原型作用域的范围是从形参定义到原型声明结束。这意味着,编译器在处理函数原型中的形参时只关心它的类型,二形参名通常无关紧要。而且,即使有形参名,也不必与函数定义中的形参名匹配。只有在变长数组中,形参名才有用。如:void use_a_VLA (int n, int m, ar[n] [m])

1.4 文件作用域

变量的定义在函数的外面,具有文件作用域。 这样的变量可用于多个函数,所以又称为全局变量。

1.5 翻译单元

​ C 预处理器实际上是用包含的头文件内容替换 #include 指令。所以,编译器源代码和所有的头文件都看成是一个包含信息的单独文件,这个文件被称为翻译单元。

二、链接

2.1 无链接

具有块作用域、函数作用域或函数原型作用域的变量都是无链接变量。

2.2 链接

具有文件作用域的变量可以是外部链接或内部链接。

2.2.1 内部链接

​ 内部链接变量只能在一个翻译单元中使用,内部链接的文件作用域又称为 “文件作用域”。

2.2.2 外部链接

​ 外部链接变量可以在多个文件中使用,外部链接的文件作用域又称为 ”全局作用域“ 或 ”程序作用域“。

三、存储期

3.1 自动存储期

​ **块作用域的变量通常都具有自动存储期。**当程序进入定义这些变量的块时,为这些变量分配内存,当退出这个块时,释放刚才为变量分配的内存。

3.2 静态存储期

文件作用域变量具有静态存储期。

​ 注:static 关键字表明了其链接属性,而非存储期。有 static 关键字的是内部链接。

3.3 线程存储期

具有线程存储期的对象,从被声明到线程结束一直存在。

3.4 动态分配存储期

使用内存分配函数分配的变量。

四、存储类别

4.1 概述

存储类别存储期作用域链接声明方式
自动自动块内
寄存器自动块内、使用关键字 register
静态外部链接静态文件外部所有函数外
静态内部链接静态文件内部所有函数外,使用关键字 static
静态无链接静态快内,使用关键字 static

4.2 特性

4.2.1 寄存器变量

​ 寄存器变量与自动变量相比,它存储在了最快的可用内存中。由于寄存器变量存在了寄存器而非内存中, 所以无法获取寄存器变量的地址。

​ 可声明为 register 的变量类型有限,因为寄存器可能没有足够大的空间来存储 64 位的变量。

4.2.2 静态变量

​ 静态变量是指在内存中原地不动,而不是它的值不变。

​ 静态变量有块静态变量、外部链接的静态变量、内部链接的静态变量。

​ 例:

#include <stdio.h>

int staticdemo(void);

int main(void)
{
        int i;

        for(i = 0; i < 10; i++)
                printf("%d ", staticdemo());	//调用声明静态变量的函数
		
   		 /*运行结果
		1 2 3 4 5 6 7 8 9 10 
		*/
        return 0;
}

int staticdemo(void)
{
        static int demo = 0;	//声明静态变量

        return ++demo;
}

分析结果:

​ 在第一次调用函数 staticdemo() 时声明静态变量并初始化为 0,之后再调用该函数,就不会对 demo 进行初始化,因为可以直接使用那个内存位置的量。

4.2.3 外部链接的静态变量

​ 如果一个源代码文件使用的外部变量定义在另一个源代码文件中,则必须使用 extern 再该文件中声明该变量。

/*file1.c*/
int exVal = 100;
int exVal2 = 200;

/*file2.c*/
#include <stdio.h>
#include "file1.c"
int main(void)
{
        extern int exVal;
    	int exVal2 = 50
        printf("exVal = %d \n", exVal);
        printf("exVal2 = %d \n", exVal2);

        return 0;
}

/*运行结果
exVal = 100
exVal2 = 50
*/

分析结果:

​ exVal 使用了 extern 关键字,所以输出是 file1.c 中定义的值,而 exVal2 并未使用 extern 关键字, 所以是 输出的是 file2.c 中定义的值。

第一次声明称为定义式声明,第二次声明称为引用式声明,只有定义式声明才能初始化变量。

4.2.4 内部连接的静态变量

​ 普通的外部变量可用于统一程序中的任意文件的函数,但内部链接的静态变量只能用于同一个文件中的函数。

例:

#include <stdio.h>

static int a = 100;

int main(void)
{
        printf("static val a = %d \n", a);

        return 0;
}
/*输出结果
static val a = 100
*/
4.2.5 动态存储变量

​ C可以在程序运行时分配更多的内存(如变长数组),我们也可以使用 malloc() 函数分配内存。malloc() 返回动态分配内存块的首字节地址。因此,可以把该地址赋给一个指针,并使用指针访问这块内存。因为 char 表示一字节,malloc() 的返回类型通常被定义为指向 char 的指针,然后使用强制类型转换转成想要的类型。

​ 例:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	int i = 0;
	double * ptd = (double *) malloc(5 * sizeof(double));      //声明 5 个空间的double数组
	int * pti = (int *) malloc(3 * sizeof(int));           //声明 10 个长度的int数组

	printf("enter 5 num to assign double arry: \n");
	while (i < 5 && scanf_s("%lf", &ptd[i]) == 1)		//获取 double 输入
		i++;
	printf("here are double arry: \n");
	for (i = 0; i < 5; i++)		//输出
		printf("%7.2f", ptd[i]);
	printf("\n");
    free(ptd);

	i = 0;
	printf("enter 3 num to assign int arry: \n");
	while (i < 3 && scanf_s("%d", &pti[i]) == 1)		//获取 int 输入
		i++;
	printf("here are int arry: \n");
	for (i = 0; i < 3; i++)		//输出
		printf("%d ", pti[i]);
    free(pti);

	return 0;
}

/*运行结果
enter 5 num to assign double arry:
9 10 4.4 8.9 10
here are double arry:
	9.00  10.00   4.40   8.90  10.00
enter 3 num to assign int arry:
4 9 10
here are int arry:
4 9 10
*/

参考书籍

C Primer Plus (第六版)中文版

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值