C语言声明(存储类别,作用域,链接属性)

声明

声明的语法

一般地,声明具有下列形式:

				声明说明符 声明符;

声明说明符(declaration specifier)描述声明的变量或函数的性质。
声明符(declarator)给出了它们的名字,并且可以提供关于其性质的额外信息。
声明说明符分为以下 4 大类:

  • 存储类型
    存储类型一共有4种:auto、static、extern 和 register。
  • 类型限定符
    C89只有两种类型限定符:const 和 volatile;C99还有一个限定符 restrict;
  • 类型说明符
    包括:(void、char、short、int、long、float、double、signed、unsigned、struct、union、enum)
  • 函数说明符
    C99 新增:inline

在声明中最多可以出现一种存储类型;如果存储类型存在,则必须把它放置在最前面。
声明可以包含零个或多个类型限定符。
类型限定符和类型说明符必须跟随在存储类型后边,但是两者的顺序没有限制。

存储类型

变量的性质

C程序中的每个变量都具有以下 3 个性质。

  • 存储期限。变量的存储期限决定了为变量预留和内存被释放的时间。
    • 具有自动存储期限的变量在所属块被执行时获得内存单元,并在块终止时释放内存单元,从而会导致变量失去值。
    • 具有静态存储期限的变量在程序运行期间占有同一个的存储单元,也就允许变量无限期地保留它的值。
  • 作用域。变量的作用域是指可以引用变量的那部分程序文本。
    • 块作用域:变量从声明的地方一直到所在块的末尾都是可见的。
    • 文件作用域:变量从声明的地方一直到所在文件的末尾都是可见的。
    • 原型作用域:它只适用于在函数原型中声明的参数名,在原型中(与函数的定义不同),参数的名字可以省略。
    • 函数作用域:它只适用于语句标签,语句标签用于 goto 语句。基本上,函数作用域可以简化为一条规则:一个函数中的所有语句标签必须唯一。
  • 链接属性。变量的链接确定了程序的不同部分可以共享此变量的范围。
    • 具有外部链接的变量可以被程序中的几个(或许全部)文件共享。
    • 具有内部链接的变量只能属于单独一个文件,但是此文件中的函数可以共享这个变量。
    • 无链接的变量属于单独一个函数,而且根本不能被共享。

变量的默认存储期限、作用域和链接都依赖于变量声明的位置:

  • 在块(包括函数体)内部声明的变量具有自动存储期限、块作用域,并且无链接。
  • 在程序的最外层(任意块外部)声明的变量具有静态存储期限、文件作用域和外部链接。
int i; //具有静态存储期限、文件作用域和外部链接
void fun(void)
{int j; //具有自动存储期限、块作用域,并且无链接
}

可以通过指定明确的存储类型(auto、static、extern 和 register)来改变变量的性质。

auto存储类型

auto 存储类型只对属于块(用花括号括起来的多个语句)的变量有效。
auto 变量具有自动存储期限、块作用域,并且无链接。
auto 存储类型几乎从来不用明确地指明,因为对于在块内部声明的变量,它是默认的。

static存储类型

static 存储类型可以用于全部变量,而无需考虑变量声明的位置。
但是,作用于块外部声明的变量和块内部声明的变量时会有不同的效果:

  • 当用在块外部时,static 说明变量具有内部链接。
  • 当用在块内部时,static 把变量的存储期限从自动的变成了静态的。
int i; //具有静态存储期限、文件作用域和内部链接
void fun(void)
{int j; //具有静态存储期限、块作用域和无链接
}

static 变量 和 auto 变量的比较:

  • 块内的 static 变量只在程序执行前进行一次初始化;而 auto 变量则会在每次出现时进行初始化。
  • 每次调用函数时,它都会获得一组新的 auto 变量;但是,如果函数含有 static 变量,那么此函数的全部调用都可以共享这个 static 变量。
  • 虽然函数不应该返回指向 auto 变量的指针,但是函数可以返回指向 static 变量的指针。

extern存储类型

extern 存储类型使几个源文件可以共享同一个变量。
变量的 extern 声明不是定义,它只是提示编译器需要访问定义在别处的变量。

file1.c
int a = 3,b = 4;//在file1.c中定义(初始化)file2.c                     
extern int a,b; //在file2.c中声明      
int main()
{printf("%d,%d\n",a,b);
}

extern 声明的变量始终具有静态存储期限,其作用域依赖于声明的位置。
在大多数情况下,变量会定义在另一个文件中,并且具有外部链接。

register存储类型

声明变量具有 register 存储类型就要求编译器把变量存储在寄存器中,而不是像其他变量一样保留在内存中。

函数的存储类型

和变量声明一样,函数声明的(和定义)也可以包括存储类型,但是选项只有 extern 和 static。
在函数声明开始处的单词 extern 说明函数具有外部链接,也就是允许其他文件调用此函数。
如果不指明函数的存储类型,那么会假设函数具有外部链接。
在函数声明开始处的单词 static 说明函数具有内部链接,也就是说只能在定义函数的文件内部调用此函数。

类型限定符

const 限定符

任何变量的声明都可以使用 const 限定符限定,该限定符指定变量的值不能被修改。
const 对象必须声明的同时初始化。

const int buffsize = 255;

初始值可以是任意复杂表达式:

int i = 42;
const int ci = i;
const int j = get_size();

默认状态下,const 对象仅在文件内有效。
如果想在多个文件之间共享 const 对象,在变量的定义和声明之前都添加 extern 关键字。

文件1extern const int buffsize = fcn(); //该常量能被其他文件访问
文件2extern const int buffsize;         //使用其它文件的常量

指向常量的指针

要想存放常量的地址,只能使用指向常量的指针(pinter to const)。
指向常量的指针不能用于改变其所指对象的值。

const double pi = 3.14;
const double* ptr = π

允许指向常量的指针指向一个非常量的对象:

double pi = 3.14;         
const double* cptr = π //不能通过*cptr改变pi的值

常量指针

允许把指针本身定位常量。
常量指针(const pointer)必须初始化,而且一旦初始化完成,它的值就不能再改变了。
把 * 放在 const 关键字之前用以说明指针是一个常量。

int errNumb = 0;
int* const curErr = &errNumb; //cuErr将一直指向errNumb

指向常量的常量指针

const double pi = 3.14159;
const double* const pip = π //指向常量对象的常量指针。

受限指针

在C99中,关键字 restrict 可以出现在指针的声明中:

int* restrict p;

用 restrict 声明的指针叫做受限指针(restricted pointer)。
这样做的目的是,如果指针 p 指向的对象在之后需要修改,那么该对象不会允许通过除指针 p 之外的任何方式访问。
其他访问对象的方式包括让另一个指针指向同一个对象,或者让指针 p 指向命名变量。

初始化

具有静态存储期限的变量的初始化必须是常量。
具有静态存储期限的变量默认情况的值为零。
具有动态存储期限的变量的初始化必须可以是变量也可以是常量。
具有动态存储期限的变量没有默认的初始值。
包含在花括号中的数组、结构或联合的初始化必须只包含常量表达式。
自动类型的结构或联合的初始化可以是另外一个结构或联合。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/187457.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

搭建Hadoop集群过程中常见错误的解决方案

格式化报错 权限问题 出现cannot creat directory或cannot creat file类型 如下报错信息: cannot create directory Permission denied如果使用的是 user 用户,多数情况下是因为文件权限问题,hadoop3.3.1、big_data(存数据&am…

【Java】14. 字符串

14. 字符串 14.1 String类的构造方法 public class StringDemo01 {public static void main(String[] args) {//public String():创建一个空白字符串对象,不含有任何内容String s1 new String();//public String(char[] chs):根据字符数组的…

SAP 如何检查已安装的SAP UI5 版本

第一个方法是直接从FLP中查看 但是部分高版本的FLP中没有这个about, 那么在当前界面可以使用:CTRL ALT SHIFT S 查看当前版本 根据此版本,去进行你的UI5的开发吧

观察者模式

1.观察者模式是什么呢? 观察者模式(有时又被称为发布-订阅Subscribe>模式、模型-视图View>模式、源-收听者Listener>模式或从属者模式)是软件设计模式的一种。在此种模式中,一个目标物件管理所有相依于它的观察者物件&am…

2分图匹配算法

定义 节点u直接无边,v之间无边,边只存在uv之间。判断方法:BFS染色法,全部染色后,相邻边不同色 无权二部图中的最大匹配 最大匹配即每一个都匹配上min(u, v)。贪心算法可能导致&…

【Unity】Blender场景导入

素材 下载场景:https://www.aplaybox.com/details/model/keDSIks72Qh3 blender文件导出为.fbx文件,路径选择复制(做的过程太乱了不知道有没有影响),物理类型选择网格,勾选应用变换 blender下的物体长度是u…

华为OD机试 - 计算三叉搜索树的高度(Java JS Python C)

题目描述 定义构造三叉搜索树规则如下: 每个节点都存有一个数,当插入一个新的数时,从根节点向下寻找,直到找到一个合适的空节点插入。查找的规则是: 如果数小于节点的数减去500,则将数插入节点的左子树如果数大于节点的数加上500,则将数插入节点的右子树否则,将数插入…

SS8813T 打印机驱动芯片

SS8813为打印机和其它电机一体化应用提供一种双通道集成电机驱动方案。SS8813有两路H桥驱动,每个H桥可提供最大峰值电流2.5A和均方根电流1.75A(在24V和Ta 25C适当散热条件下),可驱动两个刷式直流电机,或者一个双极步进电机,或者螺…

PyQt 笔记

参考文章 pyqt5:利用QFileDialog从本地选择图片\文本文档显示到label、保存图片\label文本到本地(附代码)_pyqt5中qfiledialog.getopenfileurl-CSDN博客 txt文件的打开与保存 def openTextFile(self): # 选择文本文件上传fd,fp QFileDialog.getOpen…

Xilinx FPGA——ISE的UCF时序约束

时序约束是我们对FPGA设计的要求和期望,例如,我们希望FPGA设计可以工作在多快的时钟频率下等等。 设计是要求系统中的每一个时钟都进行时序约束。 一、分组约束语法(NET、PIN、INST) TNM是最基本的分组约束语法,其语法…

【小布_ORACLE笔记】Part11-5 RMAN Backups

【小布_ORACLE笔记】Part11-5 RMAN Backups 文章目录 【小布_ORACLE笔记】Part11-5 RMAN Backups1. 增量备份(Incremental Backups)1.1差异增量备份(Differential Incremental Backup)1.2累积增量备份(Cumulative Incremental Bac…

Mysql 字符集配置修改操作

目录 服务器字符集和校对规则 数据库字符集和校对规则 表字符集和校对规则 列字符集和校对规则 例 1 连接字符集和校对规则 MySQL 服务器可以支持多种字符集,在同一台服务器、同一个数据库甚至同一个表的不同字段中,都可以使用不同的字符集。Oracl…

C#WPF本地化语言实例

本文演示C#WPF中使用.resx资源文件本地化语言实例 一、更改默认Resources.resx 文件 在解决方案资源管理器中,您将在“属性”文件夹下看到 Resources.resx 文件。将访问修饰符从内部更改为公共,以便可以在 XAML 文件中访问它。 二、创建新资源文件 默认情况下,程序使用默…

uniapp如何与原生应用进行混合开发?

目录 前言 1.集成Uniapp 2.与原生应用进行通信 3.实现原生功能 4.使用原生UI组件 结论: 前言 随着移动应用市场的不断发展,使用原生开发的应用已经不能满足用户的需求,而混合开发成为了越来越流行的选择。其中,Uniapp作为一种跨平台的开…

【开源视频联动物联网平台】写一个物联网项目捐献给Dromara组织

一、平台简介 MzMedia开源视频联动物联网平台,简单易用,更适合中小企业和个人学习使用。适用于智能家居、农业监测、水利监测、工业控制,车联网,监控直播,慢直播等场景。 支持抖音,视频号等主流短视频平台…

福州大学《嵌入式系统综合设计》 实验十一:OpenCV视频解码

一、实验目的 掌握OpenCV视频解码的流程,对比和FFMPEG的区别。 二、实验内容 搭建实验开发环境,编译并运行解码程序,对编码后的视频码流通过OpenCV进行解码。 三、开发环境 开发主机:Ubuntu 20.04.6 LTS 硬件:算…

Linux 磁盘分区处理

最近实施过程中遇到客户提供给我们的服务器操作系统和Docke容器环境都已经安装完成,但磁盘的分区没有进行整理好。磁盘总共270G,系统安装分配了60G,剩余未创建分配需要处理。由于分区情况每家不一样,但大致流程都是相同的&#xf…

[论文阅读]VoxSet——Voxel Set Transformer

VoxSet Voxel Set Transformer: A Set-to-Set Approach to 3D Object Detection from Point Clouds 论文网址:VoxSet 论文代码:VoxSet 简读论文 这篇论文提出了一个称为Voxel Set Transformer(VoxSeT)的3D目标检测模型,主要有以下几个亮点: 提出了基于…

QML学习一、GridView的使用和增加添加动画、删除动画

一、效果预览 二、源码分享 import QtQuick import QtQuick.ControlsApplicationWindow {visible: truewidth: 640height: 480title: "Test"property int cnt:cnt model.countListModel{id:modelListElement{index:0}ListElement{index:1}ListElement{index:2}List…

Docker 使用心得

创建一个docker 镜像,相关运行代码,放在docker镜像文件同级, pm2 不能与 docker一起使用() # node 服务docker FROM node:10.16.3LABEL author"sj"RUN mkdir -p /var/nodeCOPY ./node /var/nodeWORKDIR /va…