IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> C语言 | 【耗费一夜总结三本C语言系列】之 作用域 在也不用担心分不清变量的作用域拉!!! -> 正文阅读

[JavaScript知识库]C语言 | 【耗费一夜总结三本C语言系列】之 作用域 在也不用担心分不清变量的作用域拉!!!

前言

本章内容总结了作用域,分别对作用域、链接、存储期、存储类型进行概况。

在这里插入图片描述

一、数据存储🤷?♂?

众所周知,数据存储在内存中。C的强大之处能够让程序员通过内存管理系统中指定变量的作用域和生命周期。从硬件角度来看,每个值都需要占用一定的物理内存。

  • 而在C中一块内存则被称为对象。该对象可被存储一个、多个、甚至没有存储值;
  • 标识符(a)可用来访问对象的内容int a = 10
  • 存储期描述了对象在内存的保存的时间;
  • 作用域和链接描述标识符,具有多种情况:
    作用域:
    • 多文件共享;
    • 特定文件;
    • 特定函数;
    • 函数的某部分;

二、存储类别🙋?♂?

2.1 作用域

用于描述程序中标识符可被访问的区域;可以说标识符声明的位置决定了它的作用域

几种作用域

  • 块作用域;
  • 函数作用域;
  • 函数原型作用域;
  • 文件作用域;

2.1.1 块作用域

范围:在代码块声明的起始位置到块结尾;

  • 局部变量都具有块作用域;

什么是块:位于一对花括号之间,或者函数中任意的复合语句

拓展

C99以前,块作用域的变量都必须声明在块的开头。而C99允许了在块中任意位置声明变量;

// C99前使用for循环
int i;
for(i=0; i<10; ++i)
	...

// C99修订后
for(int i=0; i<10; ++i)
	...

该特性不仅仅在for循环,也应用到了while等各种语句。

举个栗子🌰:

以下标记中的变量都为块作用域

在这里插入图片描述

注意

应尽量避免在嵌套代码块中出现相同的变量名。为什么编译器可以把不同代码块的变量存储域同一个内存地址呢?若不是嵌套的代码块有且仅有一个代码块处于活动状态,它们的作用域无重叠状态,且变量不能同时存在,也不会同时存在。

2.1.2 函数作用域

范围:一个标签出现,直至函数结束,且为了防止混淆,标签尽量是唯一的;

  • 只适用于goto语句标签;

2.1.3 函数原型作用域

范围:从形参定义到原型声明结束;

  • 只适用于函数原型中的形参名,使用时无需与声明中的形参名匹配;
  • 类型重要,形参名可省略,但变长数组的形参名需要;

在这里插入图片描述

2.1.4 文件作用域(全局变量)

范围:从定义开始到文件末尾;

  • 定义在代码块之外的变量,且函数名也有具有文件作用域;

2.2 链接🧝?♂?

标识符的作用域链接属性相关;

几种链接属性

  • 外部链接【extern】;
  • 内部链接;
  • 无链接

2.2.1 外部链接【全局作用域】

可在多个源文件内使用,标识符不论在几个源文件内被声明多少次都属于一个实体;

  • 一般使用extern用于外部链接,在使用其他源文件时,需声明,便于解读;
  • 当extern的标识符,可使用static来改变它的链接属性;

案例
test.h

int x = 10;

main.cpp

/*----------------------------------------------------------------------
	> File Name: test.cpp
	> Author: Jxiepc
	> Mail: Jxiepc
	> Created Time: Wed 20 Oct 2021 12:49:44 PM CST
----------------------------------------------------------------------*/

#include<iostream>
#include<unistd.h>
#include<cstring>
#include "test.h"

extern int x;

void test01(){
	int x = 1;
	std::cout << "不加extern " << x << std::endl; 	
}

void test02(){
	std::cout << "直接使用 "<< x << std::endl;
}

void test03(){
	extern int x;
	std::cout << "函数内在使用extern " << x << std::endl;	
}

int main(int argc, char *argv[]){
	
	test01();
	test02();
	test03();

	return 0;
}

运行结果:

在这里插入图片描述

2.2.2 内部链接【文件作用域】

该链接属性的变量只能在一个翻译单元内使用;在同一个源文件内所有声明都指向一个实体,位于不同源文件则分属于不同实体。

  • 一般使用static用于内部链接;
  • extern无法改变static的链接属性;

翻译单元

即一个源文件和它所包含的头文件

2.2.3 无链接

具有块作用域、函数作用域、函数原型作用域的变量都属于无链接变量;

2.3 存储期🧙?♂?

描述了标识符访问的对象的生存期;

几种存储期

  • 静态存储期;
  • 线程存储期;
  • 自动存储期;
  • 动态分配存储期;

2.3.1 静态存储期

存在周期:程序执行期间直至程序结束;

  • 文件作用域具有静态存储器;
  • 此处的静态与static不为同一类别;
  • 静态存储期包括了内部链接外部链接所有的文件作用域变量;
  • 块作用域也可以有静态存储期;

2.3.2 线程存储期

存在周期:从被声明到线程结束;

  • 可使用_Thread_local即可获得变量的私有备份;

2.3.3 自动存储期

存在周期:当一个变量在块内声明,到块结束时,该变量会自动释放内存。

  • 当该变量释放后,其内存地址可继续被使用;
  • 块作用域(局部变量)一般都有自动存储期;
  • 变长数组较为特殊,存储期是从声明到块的末尾;

2.4 变量🧚?♂?

几种变量

  • 自动变量;
  • 寄存器变量;
  • 块作用域的静态变量;
  • 外部链接的静态变量;
  • 内部链接的静态变量;

2.5 存储类型🙇?♂?

2.5.1 自动变量

  • 即块作用域【自动存储期、无链接】中的变量;
  • 内层块会隐藏外层块的定义;

2.5.2 寄存器变量

通常变量都保存在内存当中,而寄存器变量则存储在CPU的寄存器中,更加高效。

  • 寄存器的地址无法获取
  • 其变量与自动变量几乎一致
  • 具有静态存储期;
  • 可声明为register的数据类型有限,例如double由于没有足够大的空间;
  • 使用只需在声明的时候加上register关键字;

2.5.3 块作用域【局部】的静态变量

此处的静态应理解为该变量再内存中的地址不改变,值可变;

  • static变量不能使用在形参中;
  • 内部静态存储类别

函数块内使用static

/*----------------------------------------------------------------------
	> File Name: test.cpp
	> Author: Jxiepc
	> Mail: Jxiepc
	> Created Time: Wed 20 Oct 2021 01:28:11 PM CST
----------------------------------------------------------------------*/

#include<iostream>
#include<unistd.h>
#include<cstring>

int test01(){
	static int a = 10;
	
	return a;	
}

int main(int argc, char *argv[]){
	int x = test01();
	std::cout<< x << std::endl;

	return 0;
}

由于变量在函数结束后即释放,所以无法将变量返回【有些编译器有优化,能够成功返回。如果将该变量多打印几次即会出错】。为了解决该问题,即可在变量声明前加上static关键字,保证了函数结束后,该变量不会被释放。

2.5.4 外部链接的静态变量

外部变量,可在其他文件中进行访问;

  • 外部变量具有静态存储期,即直至函数结束;
  • 具有文件作用域、外部链接、静态存储期;
  • 为外部存储类别;
  • 在其他文件使用时,必须使用extern进行声明;
  • 若外部变量没有被初始化,则会被初始化为0;

2.5.5 内部链接的静态变量

只属于一个文件内部使用,定义在文件开头,直至文件结束;

  • 具有静态存储期,文件作用域和内部链接;
  • 可使用extern在函数内部对其声明,但不会修改它的链接属性;

小结

  • 程序运行时变量存储的位置在以下三个:
    • 普通内存;
    • 运行时堆栈;
    • 硬件寄存器;
  • 不属于堆栈的变量 - 静态变量;
  • 静态变量与外部变量未初始化则会被自动初始化为0;
  • 存储类别说明符:auto、register、static、_Thread_local、typedef;

test.h

int x;

main.cpp

/*----------------------------------------------------------------------
	> File Name: test.cpp
	> Author: Jxiepc
	> Mail: Jxiepc
	> Created Time: Wed 20 Oct 2021 01:28:11 PM CST
----------------------------------------------------------------------*/

#include<iostream>
#include "test.h"

static int a;
extern int x;


int main(int argc, char *argv[]){

	std::cout << "静态变量: " << a << std::endl;
	std::cout << "外部变量: " << x << std::endl; 


	return 0;
}

结果
在这里插入图片描述

2.6 归纳表🧅

变量类型声明位置是否于堆栈作用域若声明static
全局所有代码块之外从声明到文件尾其他源文件无法访问
局部代码块起始处整个代码块不存于堆栈,直至程序结束
形式参数函数头部整个函数不允许

请添加图片描述

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-21 12:06:15  更:2021-10-21 12:06:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/10 12:47:18-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码