C语言——static与extern

一、static

用static修饰变量,就是指该变量空间独立于函数中的auto变量或者栈变量,static变量空间在内存中的静态区内分配。

二、static作用

1.修饰局部变量

  在一般情况下,局部变量是存放在栈区的,并且局部变量的生命周期在该语句块执行结束时便结束了。但是如果用static进行修饰的话,该变量便存放在静态数据区,其生命周期一直持续到整个程序执行结束为止。注意:虽然用static对局部变量进行修饰过后,其生命周期和存储空间发生了变化,但是其作用域并没有改变,它仍然是一个局部变量,作用域仅限于该语句块。
  在用static修饰局部变量后,该变量只在初次运行时进行初始化工作,且只进行一次。

代码如下(示例):

#include <stdio.h>
void fun()
{
	static int a = 1;
	a++;
	printf("%d\n",a);
}
int main(void)
{
	fun();
	fun();
	return 0;
}

程序执行结果为:

2  3

结果说明在第二次调用fun()函数时,a的值为2,并且没有进行初始化赋值,直接进行自增运算,所以得到结果为3。如果静态局部变量没有进行初始化,整型变量系统会自动对其赋值为0,对于字符数组,会自动赋值为“\0”。

2.修饰全局变量

  对于一个全局变量,它既可以在本源文件中被访问,也可以在同一个工程的其他源文件中被访问(只需用extern进行声明即可)。
代码如下(示例):

(1)file1.c

int a = 1;

(2)file2.c

#include <stdio.h>
extern int a;
int main(void)
{
	printf("%d\n",a);
	return 0;
}

则执行结果为:1
但是如果在file.c中把“int a = 1”改为“static int a = 1”,那么在file2.c是无法访问到变量a的。原因在于用static对全局变量进行修饰改变了其作用域的范围,由原来的整个工程变为了本源文件可见。

3.修饰函数

  用static修饰函数,其情况与修饰全局变量大同小异,就是改变了函数的作用域。

三、extern

extern是指当前变量或者函数不是在本源文件内声明的,它是外部变量或者外部函数。当我们在本文件里试图引用一个外部声明的全局变量或者函数时,可以在其前面加上extern,表示它是外来的。

extern可以修饰变量和函数,表示该变量或者函数在其他地方被定义(本源文件或者其他源文件内),在这里声明使用它,这样多个源文件共享变量和函数;多个c源文件的编译是独立的,所以编译器无法判断多个源文件共享的变量的类型是否一致(只判断变量名或者函数名是否一致);等到链接的时候(这个阶段已经不再进行语法检查了),多个源文件编译后的.o文件链接成一个目标文件,如果有一个以上的源文件对同一个变量进行了初始化,则报错。
可在我另一篇文章《C语言——定义与说明》中了解定义和声明的区别

四、extern的作用

1.extern变量名

  在任何函数体外声明或定义变量时,不加extern可能是定义也可能是声明,编译器选择初始化的那个(最多一个地方对它进行初始化),如果没有初始化则任选其中一个作为定义,其他作为声明,但是加extern的肯定是声明;如果不想让其他源文件链接到,则需要使用static关键字。
  在函数体内声明(注意是声明,在函数体内部不能定义外部变量)使用其他源文件中定义的变量时,必须使用extern关键字,因为在函数体内默认为局部变量。

2.extern函数

  函数默认是外部的(在函数体内或函数体外声明一个外部函数,extern关键字均可省略),如果不想让其他源文件链接到,则需要在函数前加static关键字。
注:虽然在很多情况下extern关键字都可以被省略,但是为了提高程序可读性,还是加上为好。
  前面说过,编译器并不检查多个源文件共享的变量的类型是否一致,那么下面的代码是合法的。
代码如下(示例):

char a[] = "hello";
int main()
{
	extern int a;
	printf("%x\n",a);
	return 0;
}

  同样,若多个源文件共享函数,编译器也不会对外部函数的参数类型、参数个数和返回值类型进行检查,只要函数名相同即可(也就是说在用extern声明变量时,可以不指定类型)。
代码如下(示例):

int echo(int x)
{
	return x;
}
int main()
{
	extern int echo(char);
	printf("%d\n",echo(255));
	return 0;
}

可以尝试输入以上代码注意输出值!!!
  所以在写程序时,一定要注意外部函数的参数类型、参数个数和返回值类型,最好保持一致,否则会出现意想不到的问题。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

香蕉牛奶糖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值