static、const、extern关键字的详解

一、static关键字

1.局部变量中的static

       普通局部变量就是在函数内部定义的变量(不加static修饰符)。编译器一般不对普通局部变量进行初始化,它的值在初始时是不确定的,除非对其显式赋值。普通的局部变量在栈空间上分配,这个局部变量所在的函数被多次调用时,每次调用这个局部变量在栈上的位置都不一定相同。局部变量也可以在堆上动态分配,但是记得使用完这个堆空间后要释放之。

       static局部变量叫静态局部变量。它与普通的局部变量的区别

           1)位置:静态局部变量被编译器放在全局存储区,在程序的整个生命周期中存在。

           2)访问权限:静态局部变量只能被其作用域内的变量或函数访问。也就是说虽然它会在程序的整个生命周期中存在,由于它是static的,它不能被其他的函数和源文件访问。

           3)值:静态局部变量如果没有被用户初始化,则会被编译器自动赋值为0,且只初始化一次,以后每次调用静态局部变量的时候都用上次调用后的值,可以参考下面的示例

#include <stdio.h>
//局部变量static的作用
void func(void)
{
	int n = 10;
	n++;
	printf("%d%s", n," ");
}

void func_static(void)
{
	static int n = 10;
	n++;
	printf("%d%s", n, " ");
}

int main(void)
{
	for (int i = 0; i < 5; i++) {
		func();
	}
	printf("\n");

	for (int i = 0; i < 5; i++) {
		func_static();
	}
	system("pause");
	return 0;
}

输出的结果是:


2.全局变量中的static

static修饰全局变量的时候,这个全局变量只能在本文件中访问,不能在其它文件中访问,即便是extern外部声明也不可以。 

3.函数中的static

static修饰一个函数,则这个函数的只能在本文件中调用,不能被其他文件调用。

4.作用场合

(1)不想被释放的时候,可以使用static修饰。比如修饰函数中存放在栈空间的数组。如果不想让这个数组在函数调用结束释放可以使用static修饰 
(2)考虑到数据安全性(全程想要使用全局变量的时候应该先考虑使用static)

 

5.面向对象(C++)中的static

可参考https://blog.csdn.net/computer_liuyun/article/details/29235111这篇文章的详细解答
静态数据成员 
(1)静态数据成员可以实现多个对象之间的数据共享,它是类的所有对象的共享成员,它在内存中只占一份空间,如果改变它的值,则各对象中这个数据成员的值都被改变。 
(2)静态数据成员是在程序开始运行时被分配空间,到程序结束之后才释放,只要类中指定了静态数据成员,即使不定义对象,也会为静态数据成员分配空间。 
(3)静态数据成员可以被初始化,但是只能在类体外进行初始化,若为对静态数据成员赋初值,则编译器会自动为其初始化为0 


(4)静态数据成员既可以通过对象名引用,也可以通过类名引用。

静态成员函数 
(1)静态成员函数和静态数据成员一样,他们都属于类的静态成员,而不是对象成员。 
(2)非静态成员函数有this指针,而静态成员函数没有this指针。 
(3)静态成员函数主要用来访问静态数据成员而不能访问非静态成员。

 

二、const关键字

1.修饰局部变量

const int n=1;
int const n=1;

上面两种写法都可以,值得注意的是:

  • const声明的变量只能被读
  • 必须初始化

2.修饰常量字符串

const char* str="fsadsadsa";

const修饰常量静态字符串,位于只读内存区域,不能对字符串进行修改eg:str[2]='a'是错误的。

3.修饰指针

1)常量指针(是指针指向的内容是常量,不能通过常量指针改变变量的值,仅此而已)

const int * n;
int const * n;
  • 常量指针说的是不能通过这个指针改变变量的值,但是还是可以通过其他的引用来改变变量的值的。
  • 常量指针指向的值不能改变,但是这并不是意味着指针本身不能改变,常量指针可以指向其他的地址。

2)指针常量(指针本身是个常量,不能再指向其他的地址,仅此而已)

int *const n;
  • 指针常量指向的地址不能改变,但是地址中保存的数值是可以改变的,可以通过其他指向改地址的指针来修改。

3)指向常量的常指针

指针指向的位置不能改变并且也不能通过这个指针改变变量的值,但是依然可以通过其他的普通指针改变变量的值。

const int* const p;

4.修饰函数

1)修饰函数参数

  • 防止修改指针指向的内容
void func(const int *p)
  • 防止修改指针指向的地址
void func( int* const p)
  • 以上两种的结合。

2)修饰函数的返回值

当const修饰函数的返回值时,且指针传递方式的函数返回值加 const 修饰,那么该返回值只能被赋给加const 修饰的同类型指针。 

5.修饰全局变量

       全局变量的作用域是整个文件,一旦有一个函数改变了全局变量的值,它也会影响到其他引用这个变量的函数,导致除了bug后很难发现,如果一定要用全局变量,我们应该尽量的使用const修饰符进行修饰,这样防止不必要的人为修改,使用的方法与局部变量是相同的。

 

三、extern关键字

        可置于变量或者函数前,以表示变量或者函数的定义在别的文件中。提示编译器遇到此变量或函数时,在其它模块中寻找其定义

  • 函数的声明extern关键词是可有可无的,因为函数本身不加修饰的话就是extern的。
  • 全局变量在外部使用声明时,extern关键词是必须的,如果变量无extern修饰且没有显式的初始化,同样成为变量的定义,因此此时必须加extern,而编译器在此标记存储空间在执行时加载如内存并初始化为0。
  • 局部变量的声明不能有extern的修饰,且局部变量在运行时才在堆栈部分分配内存。
  • 注意定义只有一次,声明可以有多次。

extern int a;//声明一个全局变量a

int a; //定义一个全局变量a

extern int a =0 ;//定义一个全局变量a 并给初值。

int a =0;//定义一个全局变量a,并给初值,

第四个等于第 三个,都是定义一个可以被外部使用的全局变量,并给初值。定义只能出现在一处。也就是说,不管是int a;还是extern int a=0;还是int a=0;都只能出现一次,而那个extern int a可以出现很多次。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值