C基础知识(存储类别)

简介: C基础知识(存储类别)

C语言在内存管理方面给我们提供了较为自由的操作,但我们在享有这些自由的同时,也要了解相关的规定,不然就会给程序带来很多漏洞,同时我们也要详细来了解存储类别,为以后的自由分配内存打好基础.(文章内容稍长,干货满满,可收藏后细细品看)

在了解存储类别之前,我先帮大家温习一遍相关的知识点


1.作用域

一个变量的作用域可以是块作用域,函数作用域,函数原型作用域及文件作用域

(其中函数作用域,函数原型作用域,不作为本文章重点,大家可以简单了解一下)

(1)块作用域:块就是用一对花括号括起来的区域,一般我们创建的变量都具有块作用域,具有块作用域的变量,有效区域是从定义处到包含该定义的块的末尾

看下面一段代码

int main()
{
int a=0;     //a的作用域开始
for(a=0;a<3;a++)
                     //注:for循环中的块,属于main函数块中的一个内层块
   {
     int b=0;       //b的作用域开始
   }       //b的作用域结束,即只有在for循环这个块中才能使用b
}          //a的作用域结束,可在整个main函数内使用a

需要注意的是在C99标准中,把块的概念扩展到循环和if语句所控制的代码中,即使没有被花括号括起来,它们仍属于这个块

看下面一段代码

int main()
{
  for(int a=0;a<3;a++)  //其中a属于for循环的一部分,a的作用域在for循环的块中
  {                      //离开for循环的块,a的作用域就会结束            
       int b=0; 
  }       
//到这里,a与b的作用域都结束了
}

同理,一个函数的形式参数,虽然定义在左花括号之前,但它仍属于这个函数,其作用域在这个函数块中

(2)函数作用域:仅用于goto语句的标签

这意味着即使一个标签首次出现在函数的内层块中,他的作用域可遍布至整个函数

参考下面一段代码

虽然标签flag定义在while循环块内,但它仍可作用于在它之前的if语句判断后的代码

(3)函数原型作用域:用于函数原型中的形参名(变量名)

函数原型作用域的范围从形参定义到函数原型声明结束(这里再帮大家温习一下函数的相关定义)

看如下代码

int add(int m, int n);   //函数原型,告诉编译器add函数的类型
int main()
{
  int a = 3, b = 4,c;
  c=add(a, b);        //函数调用,在此执行add函数
  printf("%d", c);
}
int add(int x,int y) //函数定义,指定了函数要做什么
{
  return x + y;
}

事实上,编译器在处理函数声明中的形参时,只关心其类型,形参名可有可无,即使有,其形参名也不必与函数定义中的形参名相同,但在变长数组中有个例外

void add( int x, int y ,int arr [x][y] );

//若前两个变量作为第三个数组的参数,其变量名是不能乱改和不写的,方括号内要写上x,y

(4)文件作用域:若一个变量具有文件作用域,则其作用域从定义处到所在文件末尾都有效

看如下代码

int a = 3;          //变量a具有文件作用域,该文件的函数都可以引用它
 void print(void)    //这样的变量也被称为全局变量
{
   printf("%d\n", a);
}
int main()
{
  printf("%d\n", a);
  print();
  return 0;
}

2.链接

介绍完作用域,我们来了解一下链接(往后涉及到文件的概念,忘记的同学可以复习一下再看)

先介绍一下翻译单元的概念,编译器会将一个源代码文件以及该源代码文件所包含的各种头文件看成一个单独文件,这个单独的文件被称为翻译单元,即一个翻译单元对应一个源代码文件及其所包含的各种头文件

如下图, 实现一个简易信息库程序,创建了一个test.c的源文件,两个头文件contact.c , contact.h以及我们包含的各种stdio.h等头文件,在程序运行时,编译器会将其看成一个翻译单元。

C语言有3种链接属性:外部链接,内部链接,无链接

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

内部链接和外部链接是相对于文件作用域而言的,内部链接只能作用于定义它的那个翻译单元,而外部链接可以作用于所有的翻译单元(较复杂的程序,会有多个源文件,即多个翻译单元)


举个例子,如下图

图中全局变量a就具有外部链接属性,源文件a组成的翻译单元与源文件b组成的翻译单元都可以使用变量a

但是变量b被static修饰,具有内部链接属性,只有源文件a这个翻译单元可以使用

如果源文件b想要引用变量a,一般要在引用时声明 extern int a; 表明这个变量来自其他文件,需要注意一点就是变量a的赋值只能是常量表达式,如果不给a赋初始值,a会被自动赋值为0,并且在b文件声明引用a时,不能给a赋值,例如extern int a=10;这是错误的。

注:具有文件作用域的变量都存储在内存的静态区中,直到程序结束才会将空间返还给内存,这与具有块作用域的变量不同,具有块作用域的变量在声明处被创建,出了包含它的块后,会自动将空间返还给内存。因此文件作用域的变量具有静态存储期,块作用域的变量具有自动存储期

(存储期:可简单理解为通过标识符访问的对象的生存期,静态存储期在程序执行期会一直存在,自动存储期会根据其作用域来判断返还超出作用域的变量的空间)

简单来说:作用域和链接是描述相应标识符的可用范围,而存储期是描述相应标识符的生存期


寄存器变量:

寄存器是在CPU上,不属于内存,因此,不可以取声明在寄存器上的变量的地址,在寄存器上声明变量需要用关键字register,并且不一定能够申请到,其作用域属于块作用域。

综上,我们可以得到以下一些存储类类别

(默认情况下,声明在块或函数头中的任何变量都属于自动存储类别)

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


目录
相关文章
|
5月前
|
人工智能 自然语言处理 Cloud Native
部署Bolt.diy测评计划
本教程介绍如何快速部署和使用云原生应用开发平台 CAP 的项目模板。通过一键部署功能,按照默认配置完成项目创建与部署,预计耗时1分钟。部署完成后,可通过访问地址进入应用示例。接着,在阿里云百炼控制台生成API-KEY,并将其复制到应用中,结合提示词进行创作。当代码生成完毕后,可预览网页效果或在控制台下载生成的代码。此流程帮助开发者高效体验AI代码生成与云端部署的全流程。
118 0
|
移动开发 JSON JavaScript
分享188个JS图片效果JS代码,总有一款适合你
分享188个JS图片效果JS代码,总有一款适合你
207 1
|
SQL 关系型数据库 数据库
【一文搞懂PGSQL】4.逻辑备份和物理备份 pg_dump/ pg_basebackup
本文介绍了PostgreSQL数据库的备份与恢复方法,包括数据和归档日志的备份,以及使用`pg_dump`和`pg_basebackup`工具进行逻辑备份和物理备份的具体操作。通过示例展示了单库和单表的备份与恢复过程,并提供了错误处理方案。此外,还详细描述了如何利用物理备份工具进行数据损坏修复及特定时间点恢复(PITR)的操作步骤,以应对误操作导致的数据丢失问题。
|
人工智能 内存技术
通义语音AI技术问题之预训练模型的推理与微调如何解决
通义语音AI技术问题之预训练模型的推理与微调如何解决
165 4
|
安全 Java 数据安全/隐私保护
构建高效网站后台:权限管理系统设计与实现
【7月更文挑战第5天】在现代Web应用开发中,权限管理是后台系统不可或缺的一部分,它确保了系统的安全性与用户数据的隐私。良好的权限管理系统能够精细控制不同用户角色对功能模块及数据资源的访问权限,从而提升系统的灵活性和安全性。本文将深入探讨权限管理的基本概念、设计思路,并通过一个简单的代码示例展示如何在Web后台中实现基本的权限控制逻辑。
764 2
DC/AC电源模块具有高效率、高可靠性和灵活性的特点,广泛应用于各种工业自动化设备
DC/AC电源模块具有高效率、高可靠性和灵活性的特点,广泛应用于各种工业自动化设备。
DC/AC电源模块具有高效率、高可靠性和灵活性的特点,广泛应用于各种工业自动化设备
|
Prometheus 监控 安全
Java一分钟之-Spring Boot Actuator:健康检查与监控
【6月更文挑战第7天】Spring Boot Actuator 提供了丰富的监控和管理端点,如健康检查、性能监控。要启用Actuator,需添加依赖并配置暴露端点。健康检查可自定义,性能监控可通过Metrics结合Micrometer集成外部系统。安全配置很重要,可以使用Spring Security保护端点。日志和环境信息管理则可通过`/loggers`和`/env`端点。正确使用Actuator能提升应用的可观察性和维护性。
1054 1
|
SQL XML Java
MyBatis 实现动态 SQL
 MyBatis 中的动态 SQL 就是SQL语句可以根据不同的情况情况来拼接不同的sql。 本文会介绍 xml 和 注解 两种方式的动态SQL实现方式。
281 1
|
数据可视化 数据挖掘 关系型数据库
招聘信息数据分析及可视化|以51JOB为例进行
招聘信息数据分析及可视化|以51JOB为例进行
699 0
|
SQL 弹性计算 Cloud Native
分布式事务 GTS 的价值和原理浅析
GTS 今年双 11 的成绩 今年 2684 亿的背后,有一个默默支撑,低调到几乎被遗忘的中间件云产品——GTS(全局事务服务,Global Transaction Service),稳稳地通过了自 2014 年诞生以来的第 5 次“大考”。
4474 84
分布式事务 GTS 的价值和原理浅析