目录
三、变量的储存类型(auto,extern,static,register)
本文不讲一些琐碎的概念,而将其实例化,来解决一些棘手的问题;
要讲函数,那得从声明、定义、调用、返回讲起
第一个函数结构。定义函数放在了调用函数之后,则需要在main函数之前进行声明。
第二个函数结构。定义函数放在了调用函数之前。那么则无需进行声明。
习惯问题:因为C语言程序总是从main函数开始,所以尽快找到main函数符合程序阅读的习惯,试想在一个很长的程序中找上半天才能找到main函数是多么不方便。
在开始之前,我们来问个小问题
1、void max( int,int );
2、void max( int a,int b );
3、max(a,b);
4、max(a,b)
上面四个代码,哪是声明,哪是调用,哪是定义
公布答案:1、2是声明,3是调用,4是定义
下面的所有实例均以这个代码来解释
- #include
- void max(int a,int b); //函数声明
-
- int main()
- {
- int a,b;
- max(a,b); //函数调用
- return 0;
- }
-
- void max(int a,int b) //函数定义
- {
- if(a>b)
- return ;
- else
- printf("a<=b");
- }
void max( int a,int a ); 或者void max( int int );
返回类型+函数名+(参数类型1,参数类型2,...)
max(a,b);
函数名(参数1,参数2),这里的参数是实参
max(int a,int b){ }
函数名(类型1+参数1,类型2+参数2,...),这里的参数是形参
以形参为主,因为编译器只知道形参的类型,不知道实参的类型,会将实参隐式转化为形参的类型
形参只能为变量,不能为常量和表达式,例如void max(7,a+b)就是错误的
函数值类型与返回值类型不一致,以函数值类型为准,会把return 语句表达式的值的类型转化为函数值的类型
return (表达式) ---->有返回值
return 表达式 ---->有返回值
return ; ---->无返回值(void类型)
局部变量 | 全局变量 |
1、main()函数内定义的变量也是局部变量,它只能在主函数内使用,但由于程序总是从main函数开始,以main函数执行完毕结束,所以main函数内定义的局部变量生存周期与全局变量相同 | 4、从模块化程序设计的观点来看,这是不利的,一般不要使用全局变量 |
2、允许在不同的函数中使用相同的变量名,它们代表不同的对象,分配不同的内存单元 | 5、全局变量与局部变量重名时,全局变量会被屏蔽,要引用需要在变量名前加两个冒号 :: |
3、在复合语句中定义的变量是局部变量,作用域在复合语句(即{}里的一系列语句共同构成)范围内,生存周期是复合语句执行的时间段 | 6、全局变量必须在所有函数之外,若想在定义全局变量之前的位置上使用,需加扩展名extern |
概念解释
- #include
-
- int fun1(int a,int b);//声明
- int fun2(int ,int);
- int fun3(int ,int);
-
- int main()
- {
- int a=3,b=4;//对1的解释
- printf("局部变量a=%d\n",a);
- printf("全局变量a=%d\n",::a);//对5的解释
-
- fun1(a,b);
- fun2(a,b);
- fun3(a,b);//函数调用
- return 0;
- }
-
- extern int d=10;//对6的解释,让fun1也能用d=4
-
- int fun1(int a,int b)//对2的解释
- {
- int c=0;//对3的解释,其他函数不能用c
-
- }
-
- int d=10;//全局变量,fun2之后的函数能用
-
- int fun2(int a,int b)//对2的解释
- {
- ...
- }
-
- int fun3(int a,int c)
- {
- ...
- }
有关储存区的相关内存概念,大家自行搜索了解。
那我们平时做练习写的程序都是定义的什么变量呢?我们来看看吧
- #include
-
- int fun1(int a,int b);//声明
- int fun2(int ,int);
- int fun3(int ,int);
-
- int main()
- {
- static int a=3,b=4; //静态局部变量
- printf("局部变量a=%d\n",a);
- printf("全局变量a=%d\n",::a);
-
- fun1(a,b);
- fun2(a,b);
- fun3(a,b);//函数调用
- return 0;
- }
-
- extern int d;//一旦把前缀写出来,就容易把定义和扩展搞混,
- //全局变量只能定义一次,没有赋值的就是扩展,赋值的就是定义
-
- int fun1(int a,int b)
- {
- auto int c=0;//局部变量的默认存储方式是auto
-
- }
-
- extern int d=10;//全局变量默认存储方式是extern
-
- int fun2(int a,int b)
- {
- ...
- }
auto型变量
一般情况下,在函数内或者复合语句内定义的变量,就是auto型变量
static型变量
static既能定义局部变量又能定义全局变量,那static修饰的静态局部变量和auto修饰的自动变量有何区别?static修饰的静态全局变量和extern修饰的全局变量有何区别?
自动变量 | ||
生存期 | 定义了该变量的源程序 | 函数或复合语句内 |
作用域 | 函数内或复合语句中,其他函数不能使用 | |
赋初值 | 若未赋初值,系统自动赋0; 如果已赋初始值,则再次调用函数时,就不会执行赋初始值的语句 | 若未赋初值,系统赋随机数; 如果已赋初始值,则再次调用函数时,还会重复执行赋初始值的语句 |
变量的值 | 一次调用函数完成后,变量的值会被保留,再次调用,还是原来的值 | 一次函数调用完成后,变量会被销毁,再次调用需要重新赋初始值 |
程序运行结果 | 1 2 3 4 5 | 1 1 1 1 1 |
- //定义静态局部变量
- #include
- int main()
- {
- int i;
- void fun();
-
- for(i=1;i<=5;i++)
- fun(); //函数调用
- return 0;
- }
- void fun()
- {
- static int j=0;
- j++;
- printf("%d ",j);
- }
-
-
- //定义自动变量
- #include
- int main()
- {
- int i;
- void fun();
-
- for(i=1;i<=5;i++)
- fun(); //函数调用
- return 0;
- }
- void fun()
- {
- auto int j=0;
- j++;
- printf("%d ",j);
- }
-
静态全局变量 | 全局变量 | |
生存期 | 定义了该变量的源文件 | 整个源文件 |
作用域 | 在定义了该变量的源文件内有效 | 同一源程序的所有源文件都有效 |
- //假设一个源程序由源文件test_1和test_2组成
- //test_1.c
- int a,b; //定义全局变量
- static char ch;//定义静态全局变量
- int main()
- {
- ...
- }
-
- //test_2
- extern int a,b;//正确a,b是全局变量
- extern char ch;//错误,ch是静态全局变量
- fun()
- {
- ...
- }
👍🏻点赞,你的认可是我创作的动力!
⭐收藏,你的青睐是我努力的方向!
✏️评论,你的意见是我进步的财富!