C语言关键字 - static

每天进步一点点。


若萌新总结有误,望牛人不吝赐教。>_<


static在不同的环境具有不同的意思,这确实很不幸,因为这总是会给c程序员新手带来麻烦。它既是一个自私的关键字鄙视,又是一个大方的关键字生气,为什么这么说呢?如下文所示。

在c语言中当我们需要使用一个变量或者函数时,我们不得不考虑的两点就是它们的作用域(决定它可以被谁使用)和生命周期(决定它可以被使用到什么时候),static关键字用于改变这两种属性。

一、static改变作用域(自私快哭了)。

在某些c程序中你可能添加不止一个源文件,这个时候,每个源文件中的内容能否在其它的源文件中起作用,这就可能和static有关了。我们通过一个例子来看看:

这是test1.c:

#include <stdio.h>
#include <windows.h>

int main()
{
	extern int n;
	printf("%d\n", n);

	system("pause");
	return 0;
}
这是test2.c:

int n = 10;
下面是运行结果:



通过上面例子我们可以看到,我们在test2中定义并初始化了一个全局变量n(注意该变量在代码块外部,即对于test2.c来说它时全局变量,虽然test2中并没有代码块),在test1中声明并使用它(至于为什么用extern,我们暂时不管它),程序正常运行。由此我们可以得出test2中的变量具有全局作用域,即它可以在其它任何一个源文件中被使用。但是当我们把test2.c改为如下时:

static int n = 10;


也就是使用static修饰全局变量n时,编译器直接报错说n是一个无法解析的外部符号,原因是什么呢?因为当n被static修饰时,它只在test2中有作用,所以当我们试图在test1中使用它时,编译器找不到n,所以编译器认为n没有被定义。

除了修饰变量之外,static还可以修饰函数,如下:

test1.c:

#include <stdio.h>
#include <windows.h>

extern void fun1();

int main()
{
	
	fun1();

	system("pause");
	return 0;
}

test2.c:

#include <stdio.h>

void fun1()
{
	printf("Hello world!\n");
}

运行结果:



我们在test1.c中调用test2.c中的函数时,运行正常,但是,用static修饰test_2.c中的函数时,编译器就会报错说fun1是一个无法解析的外部符号,也就是说fun1没有被定义,原因和上面static修饰变量相同。虽然fun1用static修饰后只能在test2中使用,但是我们可以通过其它手段,让它在test1中使用,如下:

test1.c:

#include <stdio.h>
#include <windows.h>

extern void fun2();

int main()
{
	
	fun2();

	system("pause");
	return 0;
}
test2.c:

#include <stdio.h>

static void fun1()
{
	printf("Hello world!\n");
}

void fun2()
{
	printf("I want to use fun1!\n");
	fun1();
}

运行结果:


我们让fun2在test2.c 中调用fun1,然后我们在test1.c中再调用fun2,这样,也达到了在test1.c中调用fun 1的目的。

通过以上测试,我们搞清楚了static的第一个作用——改变修饰内容的作用域。即static只允许本源文件使用被它修饰的内容,是不是很自私。

!!这里要注意:

1、static修饰全局变量时才会改变其作用域(可以被其它源文件使用 ——> 只能自己使用)。

2、static修饰函数时,该函数并不是绝对的只能被该源文件使用,我们可以另辟蹊径使用它。

二、改变生命周期(大方生气)。

变量的储存类型(storage class)是指储存变量的内存类型。变量的储存类型决定它何时创建、何时销毁、以及它的值能保持多久。有一下几个地方可以储存变量:堆区,栈区,静态全局区,寄存器。。。

变量的储存类型取决于它的声明位置和修饰符。在任何代码块之外声明的变量储存于静态全局区,这类变量在程序运行之前创建,在程序的整个执行期间存在。它始终保持原先的值,除非你给他赋一个新值。

对于在代码内部的变量,它们默认的是自动变量,即执行到该代码块是被创建,执行完毕后该变量被释放,我们可以通过关键字static改变它的储存类型(自动变量——>静态变量),即改变它的生命周期,使它在整个程序运行期间一直存在。我们通过以下例子来详细了解它。

#include <stdio.h>
#include <windows.h>

int main()
{
	int i = 0;
	
	for(i = 0; i < 10; i++)
	{
		int n = 1;
		printf("%d\n", n);
		n++;
	}

	system("pause");
	return 0;
}
运行结果:


在每趟循环开始的时候,我们定义n=1,然后打印,在循环结束时销毁,所以打印结果全是1。那么当使用static修饰n的时候,如下:

#include <stdio.h>
#include <windows.h>

int main()
{
	int i = 0;
	
	for(i = 0; i < 10; i++)
	{
		static int n = 1;
		printf("%d\n", n);
		n++;
	}

	system("pause");
	return 0;
}
运行结果:



打印结果是从1到10,是不是有点出乎意料。原因是我们使用static修饰n时,n被存放在了静态区,它在程序的整个执行过程中都不会被销毁,所以,当第二趟循环开始的时候,static int n = 1并没有起作用,程序是在第一趟的基础上使用n的值。这样来看,1-10的结果也就理所应当了。

由此来看,static是不是也很大方啊,它允许你使用前面“旧”值。


总结:

static作用:

1、修饰函数,改变作用域(其它源文件——>仅本源文件)。

2、修饰全局变量,改变作用域(其它源文件——>仅本源文件)。

3、修饰局部变量,改变生命周期(储存类型)(自动——>静态)。


成于坚持,败于止步!


【作者:果冻 http://blog.csdn.net/jelly_9






















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值