目录:
1.const
2.static
3.extern
一.const
1.用于定义常量变量,这样这个变量在后面久不可以再背修改。
例:当想去修改val的值时,就会报错。

注意:const仅仅用来修饰右边的变量(基本数据变量p,指针变量*p,对象变量)
// 定义int变量
int a = 66;
int b = 88;
// 定义指向a的指针变量
int *p=&a;
// 修改p的地址
p = &b;
*p = 30;
NSLog(@"%d",b);
结果分析:首先p是指向a的指针,p保存的是a的地址,p=&b时,p变成的指向b的指针,所以*p=30,其实就是给b附值,所以打印结果为30。
// 用const修饰指针变量
int * const p = &a;
此时
(1) p=&b;
(2) *p=30;
结果分析:上面解释了const是修饰右边的变量是只读的,所以说p是只读的那么(1)就会报错。
const int * p = &a;
此时
(1) p=&b;
(2) *p=30;
结果分析:*p是只读的那么(2)就会报错。
有两个更变态的写法
int const * const p = &a; // *p:只读 p:只读
const int * const p = &a; // *p:只读 p:只读
2. 保护传参时参数不被修改,如果使用引用传递参数或按地址传递参数给一个函数,在这个函数里这个参数的值若被修改,
则函数外部传进来的变量的值也发生改变,若想保护传进来的变量不被修改,可以使用const保护。
例:

3.const定义常量和宏定义常量区别
宏常量:只是在预处理器里进行文本替换,没有类型,不做任何类型检查,编译器可以对相同的字符串进行优化。只保存一份到 .rodata 段。甚至有相同后缀的字符串也可以优化,你可以用GCC 编译测试,"Hello world" 与 "world" 两个字符串,只存储前面一个。取的时候只需要给前面和中间的地址,如果是整形、浮点型会有多份拷贝,但这些数写在指令中。占的只是代码段而已,大量用宏会导致二进制文件变大 。
const常量:共享一块内存空间,就算项目中N处用到,也不会分配N块内存空间,可以根据const修饰的位置设定能否修改,在编译阶段会执行类型检查。
二.static
C语言代码是以文件为单位来组织的,在一个源程序的所有源文件中,一个外部变量(注意不是局部变量)或者函数只能在一个源程序中定义一次,如果有重复定义的话编译器就会报错。伴随着不同源文件变量和函数之间的相互引用以及相互独立的关系,产生了extern和static关键字。
一个进程在内存中的布局如图所示:

.text段保存进程所执行的程序二进制文件;
.data段保存进程所有的已初始化的全局变量
.bss段保存进程未初始化的全局变量
在进程的整个生命周期中,.data段和.bss段内的数据时跟整个进程同生共死的,也就是在进程结束之后这些数据才会寿终就寝。
1.static修饰全局变量
当一个进程的全局变量被声明为static之后,它的中文名叫静态全局变量。静态全局变量和其他的全局变量的存储地点并没有区别,都是在.data段(已初始化)或者.bss段(未初始化)内,但是它只在定义它的源文件内有效,其他源文件无法访问它。所以,普通全局变量穿上static外衣后,它就变成了新娘,已心有所属,只能被定义它的源文件(新郎)中的变量或函数访问。
例:


分析:在任何位置都可以通过extern访问到age
当我们将这个age使用static修饰后会如何呢?


分析:一旦全局变量使用static修饰之后,就只能在声明该变量的文件中访问了,其他文件访问不了。
2.static修饰局部变量
static局部变量中文名叫静态局部变量。它与普通的局部变量比起来有如下几个区别:
1)位置:静态局部变量被编译器放在全局存储区.data(注意:不在.bss段内,原因见3)),所以它虽然是局部的,但是在程序的整个生命周期中存在。
2)访问权限:静态局部变量只能被其作用域内的变量或函数访问。也就是说虽然它会在程序的整个生命周期中存在,由于它是static的,它不能被其他的函数和源文件访问。
3)值:静态局部变量如果没有被用户初始化,则会被编译器自动赋值为0,以后每次调用静态局部变量的时候都用上次调用后的值。每次函数调用静态局部变量的时候都修改它然后离开,下次读的时候从全局存储区读出的静态局部变量就是上次修改后的值。
例:

分析:time为局部变量,所以当方法aboutstatic执行完毕后,就会销毁,当下次再调用的时候time又会被初始化为10,所以3次输出结果都为9。
当局部变量被static修饰后:

分析:由于time是静态的局部变量,所以当方法第一次执行后time被初始化之后,就会在程序的整个生命周期中存在,所以当第二次调用方法的时候,time的值为第一次方法执行完毕后的值,即9。
三.extern
只是用来获取全局变量(包括全局静态变量)的值(非源文件中取全局变量必须使用extern),不能用于定义变量。extern工作原理:先在当前文件查找有没有全局变量,没有找到,才会去其他文件查找。
四.static与const联合使用
iOS中staic和const常用使用场景,是用来代替宏,把一个经常使用的字符串常量,定义成静态全局只读变量.
// 开发中禁止拿修改key值,因此用const修饰key,表示key只读,不允许修改。
static NSString * const key = @"name";
// 如果 const修饰 *key1,表示*key1只读,key1还是能改变。
static NSString const *key1 = @"name";
网友评论