一、变量的分类

按作用域分
(一) 局部变量:
- 含义:在一个函数内部定义的变量或者函数的形参,统称为局部变量。
- 在一个函数内部复合语句里定义的变量,只在这个复合语句内有效。这种复合语句也叫分程序或者程序块。
- 局部变量的使用范围:只能在本函数内部使用。不同函数可以有相同的变量名,
(二) 全局变量:
- 含义:在所有函数外部定义的变量。
- 全局变量的使用范围为从定义位置开始到本源文件结束。
- 不成文习惯:将全局变量的名字首字母大写。
局部变量和全局变量的命名冲突的问题:
- 在一个函数内部如果定义的局部变量的名字和全局变量名一样时,局部变量会屏蔽掉全局变量。
按变量的存储方式分——从变量的存在时间(生存期)角度
变量的存储方式分为静态存储方式和动态存储方式
| 用户区 |
内容 |
| 程序区 |
|
| 静态存储区 |
全局变量 |
| 动态存储区 |
函数形参、自动变量、现场保护和返回地址 |
静态存储
(一) 静态局部变量 static
- 有时候需要函数调用结束后不让系统释放空间,还保留运算后的结果,就需要定义一个静态局部变量。
- 静态局部变量在静态存储区内分配存储单元,在整个程序运行期间内都不释放,而动态变量在函数调用结束后就释放。
- 对于静态局部变量时在编译时赋初值的,只赋初值一次。以后每次调用函数时不再对变量赋初值,而是保留上次调用结束的值。
int Sum(int m)
{
static int a = 100;
a = a + m;
return a;
}
int main (void)
{
printf("第一次加1:%d\n",Sum(1));
printf("第二次加1:%d\n",Sum(1));
return 0;
}
//输出
第一次加1:101
第二次加1:102
- 长期占用内存不释放,调用函数多次时会搞不清楚当前静态变量的值到底是什么,降低了程序的可读性。
(二) 静态外部变量
- 限制某些外部变量只能在本文件中使用,而不能被其他文件所引用。
- 加上 static 只能用于本文件的外部变量为静态外部变量。 static int A;
- 这样即使 另一个文件写了 extern A;也不能使用。
注意:
- 对于局部变量来说,声明存储类型的作用是指定变量的存储区域(静态存储区或者动态存储区)
- 对于全局变量,都是在编译时分配内存的,声明存储类型的作用是为了作用域扩展问题。
- 对于局部变量用 static 声明,把它分配在静态存储区,该变量在整个程序执行期间不释放,其所分配的空间始终都在。
- 对于全局变量使用 static 声明,则该变量的作用域只限于本文件。
(三) 外部变量(即非静态的外部变量)
- 外部变量是在函数外部定义的全局变量
- 一般来说,外部变量的作用域为定义处到本文件结束。可以对其定义域进行扩展。
扩展外部变量的定义域
① 在一个文件内扩展外部变量的作用域
因为作用范围是从定义处开始的,怎么样才能在定义处上边也可以用该外部变量呢?
在引用前加上 extern 表示把外部变量的作用域扩展到当前,这叫做 外部变量声明
# include <stdio.h>
int main(void)
{
extern A,B,C; //外部变量声明,将外部变量A,B,C的作用域扩展到此处
A=B=C=100;
printf ("%d %d %d\n",A,B,C);
return 0;
}
int A,B,C;
//输出:100 100 100
② 在外部变量的作用域扩展到其他文件
- 一个C程序有很多源文件构成,如果在不同的源文件中定义了名字相同的外部变量,在连接时会报错“重复定义”
- 为避免这种情况,可采用一个源文件定义外部变量,另一个源文件将这个外部变量的作用域扩展到本文件。
- 还是采用关键字 extern ,在需要扩展的文件开头加上 extern 外部变量名
注意:系统如何识别 extern 是扩展本文件的外部变量作用域还是扩展其他源文件的外部变量作用域?
采用就近原则,如果本文件已经定义了要扩展的变量,就默认为扩展本文件的,没有则去其他源文件寻找。
动态存储
(一) 自动变量 auto —— 动态局部变量
- auto 只能用来修饰局部变量。
- 函数中的局部变量,如果不专门声明为static(静态)存储类别,都是动态的分配存储空间的,数据存储在动态存储区中。
- 函数形参和函数中定义的变量一般都属于自动变量,这些变量系统会在调用函数时动态的分配存储空间,而函数调用结束后就会自动释放分配的空间。
int main (void)
{
int a = 1;
}
//默认情况下,这里的 a 是一个自动变量,所以auto 可以不加
(二) 寄存器变量 register
- register 只能用来修饰局部变量,但它不一定成为一个寄存器变量,能不能成为一个寄存器变量需要根据编译系统来决定。
- 一些编译系统会把反复使用的变量放到寄存器里。
- 如下图,寄存器在CPU,CPU运算速度极快,变量放到寄存器,就可以在运算时免从内存取出变量在运算器运算,加快运行效率。
二、变量的作用域、可见性、存在性、生存期
(一)作用域&可见性
一个变量在某个文件或者函数范围内是有效的,就称该范围为该变量的作用域。
在作用域内可引用该变量,九城该变量在此作用域内可见。
(二)存在性&生存期
如果某一时刻该变量占用内存,则该变量在这一时刻是存在的,这一时刻属于该变量的生存期

三、变量的声明和定义
广义上的声明:包括定义性声明和引用性声明,其中定义性声明需要建立存储空间,例如:int a; 为了简便,通常叫做“定义”; 而引用性声明不需要建立存储空间,例如: extern a; 通常叫“声明”。
狭义的“声明”:不需要建立存储空间
定义:需要建立存储空间
四、内部函数和外部函数
内部函数
函数的本质就是“全局”的,构建一个函数的目的就是为了让本文件或者其他文件调用。
可以通过加 static 限制某一函数只能在本文件被调用,这样的函数叫做内部函数(静态函数)。
static int NameA(形参表列)
{
函数体;
}
外部函数
函数定义时,在类型名的前边 加上 extern 则为外部函数,可以被其他文件所调用,在类型名前面什么都没加,默认是外部函数。
1. 第一种
extern int NameB(形参表列)
{
函数体;
}
1. 第二种
int NameC(形参表列)
{
函数体;
}
本文章使用limfx的vsocde插件快速发布