| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> 【C语言】从空间和时间两个角度看一个变量 -> 正文阅读 |
|
[C++知识库]【C语言】从空间和时间两个角度看一个变量 |
一、从空间角度看变量1、作用域变量被定义的位置决定变量的作用范围,即作用域。 (1)代码块作用域什么是代码块? 在代码块中定义的变量具有代码块作用域。 如:
main函数中定义的res:
while循环中的m:
for循环中定义的i:
for内部定义的m:
以上变量都具有代码块作用域 另外,比较特殊的是函数的形参也具有代码块作用域:
调用函数时相当于进行如下操作:
由此可看出形参也具有代码块作用域。 (2)文件作用域在代码块外定义的变量具有文件作用域。 因此全局变量具有文件作用域,另外函数名定义在代码块之外,因此也具有文件作用域。 具有文件作用域的标识符作用域是从声明位置开始到文件结尾。 以下面这个程序为例:
程序中的func,main,count都具有文件作用域。 其中func的作用范围为红框所示范围: (3)函数原型作用域在函数声明(函数原型)中定义的形参具有函数原型作用域。 函数原型作用域是4种作用域中作用范围最小的,其作用范围为形参定义处到原型声明结束。 (4)函数作用域仅适用于goto语句的标签。 只要函数中出现goto语句的标签,该标签的作用范围就是整个函数。 由于编程中要避免使用goto语句,所以该部分不再细讲。 下面对四种作用域进行了总结:
2、链接属性应用场景:不同文件中出现相同标识符,怎么判定是不是同一个实体? 功能:用于认定不同文件的标识符(变量名、函数名)是否是同一个实体。 更通俗地说,就是在两个不同文件中的变量、函数声明是否指向同一个实体。 比如:a、b文件同时声明了变量c,链接属性就指定了这两处变量c是否是同一个c。 (1)external(外部的)~与extern配合使用多个文件中声明的同名标识符表示同一个实体。 程序的全局变量、所有函数默认的链接属性为external。 用extern关键字在声明中指定以引用其他文件中定义的相同标识符。 具有文件作用域的标识符默认具有external链接属性,这并不是说在b文件中不声明就可以使用a文件中定义的标识符,想要使用必须加extern关键字!
以上两个文件存在一个目录下面,使用gcc test1.c a.c -Wall && ./a.out执行结果为1。 但如果删掉声明部分extern int count;以及void a(void);就会报错。 (2)internal(内部的)~与static配合使用单个文件中声明的同名标识符表示同一个实体。 用static关键字在声明中指定让标识符变为该文件私有。 用static关键字可以使得原先具有external属性的标识符变为internal属性
(3)none(无)~无对应关键字声明的同名标识符被当做独立不同的实体 除了全局变量、所有函数,其余标识符的默认链接属性为none,如局部变量,函数形参,标签
二、从时间角度看变量1、生存期生存期用来描述一个标识符从建立到销毁的时间长度。 (1)静态存储器——高寿具有文件作用域的变量具有静态存储器,即全局变量和函数名。 全局变量和函数名一旦定义,直到程序关闭才被释放,因为他们存在全局区。 (2)自动存储器——短命具有代码块作用域的变量具有自动存储器,即局部变量,形参等。 变量在代码块运行结束时就自动释放存储空间,因为他们存在栈区。
三、存储类型定义一个变量,实际的格式为:
我们常用的int a; C语言的标识符通过作用域、链接属性、生存期可组合成多种存储方案。 1、自动auto在代码块中声明的变量默认存储类型为auto,包括局部变量、形参等。 它具有代码块作用域,无链接属性(none),自动存储期。 auto不能修饰全局变量! 2、寄存器变量register寄存器存在于CPU内部,寄存器的读写速度是最快的。 将一个变量声明为寄存器变量,该变量就有可能被存在寄存器中,因为寄存器空间十分有限,不是你想存就能存的,编译器会自己判断是否存入寄存器。如果编译器认为没有必要存入寄存器,那么该变量就会退化为auto。 它也具有代码块作用域,无链接属性(none),自动存储期。 register只能修饰局部变量不能修饰全局变量!因为修饰全局变量会一直占用寄存器。 不能获取register变量的地址! 3、静态外部链接——用extern修饰的全局变量或函数用extern修饰全局变量或者函数名,其他文件将可以访问该全局变量或者调用该函数。 如下所示:
其实跟auto一样,extern不加也行:
但程序中int count;会让人误以为又定义了一个新变量,其实它只是一个声明而已了,因此,最好还是加上extern。 静态外部链接存储类型具有文件作用域,外部链接属性(external),静态存储期。 4、静态内部链接——用static修饰全局变量或函数用static修饰全局变量或者函数,其链接属性将由external变为internal,其作用范围被限制在当前文件,其他文件无法访问。 如果某个全局变量或者函数仅在当前文件有使用到,可以加上static。 静态内部链接存储类型具有文件作用域,internal链接属性和静态存储期。 5、静态无链接——用static修饰的局部变量用static修饰局部变量,该变量的生存期将由自动存储期变为静态存储期,跟全局变量和函数一样,直到程序结束才销毁。 它具有代码块作用域,无链接属性(none),静态存储期。 不能用static修饰形参!
对比静态内部链接和静态无链接: 四、总结从空间角度看变量,即想要认清一个变量,更准确的说法是一个标识符,它的势力范围是什么。 一个标识符的定义位置决定了它的作用域: 无论什么标识符,都自带链接属性: 从时间角度来看,标识符有长寿的也有短命的 C语言的标识符通过作用域、链接属性、生存期可组合成多种存储方案:
其中只有5个有意义。 五、答疑1、多文件编程中的文件作用域待解答 2、具有文件作用域的标识符作用范围是单个文件还是多个文件?具有文件作用域的标识符默认具有外部链接属性,也就是说是有作用于多个文件的潜力的,但光有潜力还不够,想要在另一个文件中访问当前文件中的标识符,必须在另一个文件中声明,全局变量最好加上extern关键字,函数可加可不加。 3、全局变量的存储类型是什么?全局变量默认具有静态外部链接存储属性,加不加extern都一样,但最好是加上。 用static修饰的全局变量具有静态内部链接属性,仅在当前文件可以被访问。 4、哪些是局部变量?(1)函数中包括main函数中定义的变量为局部变量
(4)for中定义的变量
参考资料1、https://www.cnblogs.com/p0ise/p/c-language-linkage.html#:~:text=什么是链接属性,是否是同一个c。 |
|
C++知识库 最新文章 |
【C++】友元、嵌套类、异常、RTTI、类型转换 |
通讯录的思路与实现(C语言) |
C++PrimerPlus 第七章 函数-C++的编程模块( |
Problem C: 算法9-9~9-12:平衡二叉树的基本 |
MSVC C++ UTF-8编程 |
C++进阶 多态原理 |
简单string类c++实现 |
我的年度总结 |
【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
c语言常见错误合集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 | -2025/1/11 12:33:28- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |