变量存储相关(待完善)
内容概要
一、局部变量、全局变量与作用域
二、生存周期和存储类型
三、衔接属性
1、局部变量、全局变量与作用域
作用域规定了元素作用的范围,这样让程序变得更有序
c语言作用域有4中,分别为
代码块作用域
文件作用域
原型作用域
函数作用域
-代码块作用域
与python不同,python中代码块是通过缩进区分的;而c语言是通过大括号进行区分
c语言中在不同代码块定义的变量是互不影响的
#include <stdio.h> int main(void){ int i = 10; { int i = 20; { int i = 30; printf("i1:%d\n",i); } { int i = 40; printf("i2:%d\n",i); } printf("i3:%d\n",i); } printf("i4:%d\n",i); return 0; }
这种区分也体现在for循环中,注意()定义的i也属于下一个代码块
#include <stdio.h> int main(void){ int i = 100; printf("start : %d\n",i); for(int i = 10; i<20; i++){ printf("%d\n",i); } printf("end : %d\n",i); return 0; }
-代码块变量查询顺序
与python中变量查询顺序B(内置),G(全局),E(外部),L(局部)类似, **这里忘了**
c语言中变量查询也是按照从内往外,不走同级的规律查找的
#include <stdio.h> int main(void){ //代码块1 int i = 10; { //代码块2 int i = 20; { //代码块3 int i = 30; } { //代码块4,与代码块3同级 printf("i2:%d\n",i); //打印结果为20 } } return 0; }
-局部变量(局部变量就可以只是指代码块作用域下的变量)
可以将局部变量理解为定义在函数体的变量,这样的变量其它的函数无法访问
#include <stdio.h> int number(void); int number(void){ int i = 10; return i; } int main(void){ int i; number(); printf("%d\n",i); return 0; }
-全局变量,如果想要变量能被每一个函数访问,那么就使用全局变量,全局变量在函数外定义
#include <stdio.h> int Global_a; //默认初始化为0;全局变量命名最好为首字母大写 void a(void); void b(void); void c(void); void a(void){ Global_a++; } void b(void){ Global_a++; } void c(void){ Global_a++; } int main(void){ a(); b(); c(); c(); printf("%d\n",Global_a); return 0; }
覆盖全局变量
#include <stdio.h> int Global_a; // void a(void); void b(void); void c(void); void a(void){ Global_a++; } void b(void){ Global_a++; } void c(void){ Global_a++; } int main(void){ a(); b(); c(); c(); int Global_a = 10; //按照循序查找,优先查找语句所在代码块,如果存在变量,则忽略全局变量 printf("%d\n",Global_a); return 0; }
-文件作用域
全局变量所在的作用域就是全局作用域,它能被所有文件中其它元素访问

在python中内置命名空间、全局命名空间、局部命名空间其实并非是包含嵌套关系;
而是在内存中有不同的划分,只是彼此又有关联;
但为了方便理解,就理解为包含关系了。
c语言不知道是不是这样 **有空去详细了解一下**
-原型作用域
原型作用域使用的少,这个作用域适用于函数原型中的参数名
-函数作用域
函数作用域只适用于goto语句的标签,作用是将goto标签限制在同一个函数中,以防出现重名标签的情况
2、生存周期和存储类型
c语言只有两种生存周期
-静态存储期
静态存储期指的是从程序执行到程序结束位置,都占用着内存空间
一般具有文件作用域的元素都具有静态存储期
-自动存储期
自动存储器指的是在所在代码块结束之后,自动释放内存空间
一般具有代码块作用域的元素具有自动存储器
存储类型
对于存储类型,我是这样子理解的——内存中数据不是随机存放的,而是经过区域划分的,定义auto类型,就是告诉编译器,我要将这个变量存放到哪个内存区域中
不同的内存区域对应着不同的生存期,用户权限,作用域等等 **这部分是要核实的**
static和extern在代码块作用域和文件作用域下有不同功能
-auto存储类型
定义在函数内的变量默认的存储类型就是auto,auto存储类型的数据具有自动存储期、代码块作用域、None链接属性
int main(void){ int i = 10; // 等价于auto int i =10; return 0; }
-register存储类型
使用register修饰的变量称为寄存器变量,寄存器变量有可能存储于寄存器中,寄存器可以理解为存储空间非常小的内存,寄存器是用于存放那些频繁被cpu使用或者是即将被cpu使用的值,
cpu与寄存器之间交互数据几乎没有延迟。
但由于寄存器空间非常小,一般只有一个值,也有可能因为空间不够,或者编译器觉得有更好的变量应该被存放于寄存器。你所定义的寄存器变量实际不会存储与寄存器中。
与auto存储类型数据一样,register存储类型具有自动存储期、代码块作用域、None链接属性
不同的是,你无法通过&取值运算符来操作register变量 **实操在dev c++下可以取址,还能改值**
#include <stdio.h> int main(void){ register int i = 20; int *pi = &i; *pi = 10; printf("i: %d\n",*pi); return 0; }
-static存储类型
使用static修饰一个代码块作用域下变量,将它改变为静态局部变量。拥有代码块作用域,静态存储类型,None链接属性
#include <stdio.h> int add(void); int add(void){ static int count = 0; printf("%d\n",count); count++; } int main(void){ for(int i=0; i<10; i++){ add(); //调用函数之后变量count并没有被回收 } return 0; }
对比
#include <stdio.h> int add(void); int add(void){ int count = 0; printf("%d\n",count); count++; } int main(void){ for(int i=0; i<10; i++){ add(); } return 0; }
尝试访问这个静态局部变量
#include <stdio.h> void add(void); void add(void){ static int count = 0; printf("%d\n",count); count++; } int main(void){ for(int i=0; i<10; i++){ add(); } printf("%d\n",count); //[Error] 'count' was not declared in this scope变量未定义 return 0; }
-extern存储类型
extern可以修饰变量的声明,使得变量可以在其它文件作用域下定义
同时编译运行两个文件
a.c
int i = 10;
b.c
#include <stdio.h> int main(void){ extern int i; //声明了变量i,将它的链接属性设置为external,这样它就可以访问其它文件下的文件作用域的同名变量了 printf("i: %d\n",i); return 0; }
将b.c稍加修改之后 **待实操**
#include <stdio.h> int main(void){ extern int i; i = 10; printf("i: %d\n",i); return 0; }
使用extern的函数依旧无法使用其它代码块下的变量定义
#include <stdio.h> int main(void){ { int i = 10; } { extern int i; printf("i:%d\n",i); } return 0; }
-typeof存储类型
**待补充**
3、链接属性
链接属性说明了
链接属性,分为3种
-external链接属性
在文件作用域下定义的变量或者函数默认的链接属性就是external属性
#include <stdio.h> int i = 10; // 等价于extern int i = 10;
拥有external链接属性的变量或函数可以被来自不同文件作用域访问,当然本文件也可以
-internal链接属性
拥有internal链接属性的变量只能被本文件其它元素访问,拒绝来自其它文件作用域的访问
a.c
static int i = 20; //在文件作用域下使用static将变量链接属性改为internal
b.c
#include <stdio.h> int main(void){ extern int i; printf("int main i: %d",i); //将不能访问到a.c文件下的i,这样的目的是为了保护变量 return 0; }
-none空链接属性
拒绝所有除非下层代码块作用下元素的访问
***待补充***
本文来自博客园,作者:口乞厂几,转载请注明原文链接:https://www.cnblogs.com/laijianwei/p/14539460.html

浙公网安备 33010602011771号