c语言extern与const,static、const、extern的正确使用方式

static、const、extern的正确使用方式

1.extern

全局变量extern,也称之为外部变量,是在方法外部定义的变量。它不属于那个方法,而是属于整个源程序。作用于是整个程序。如果全局变量和局部变量重名,则在局部变量作用域内,全局变量被屏蔽,不起作用

///> DDExtern.h

#import

NSString *flag = @"DDExtension";

@interface DDExtern : NSObject

@end

定义了一个字符串 flag

///> main.m

#import

int main(int argc, const char \* argv\[\]) {

extern NSString *flag;

NSLog(@"%@",flag);

return 0;

}

打印结果:DDExtension

从例子中可以看出,main.m无需导入JJExtern的头文件,直接在NSString *flag前面加上extern关键字就可以取到JJExtern的flag值。

需要注意的是,extern修饰的变量名必须是和Extern下的变量名一致,即都为flag,否则会都提示找不到。

还需要注意extern修饰的变量是没有真的内存的。

总结:

想要访问全局变量,可以在变量前加一个extern

extern修饰的变量没有真正的内存

问题:

既然只需要extern就能得到并修改其他文件的变量,这样不是很不安全?因为随时都会被人改掉,怎么办??

答案:

使用接下来所讲的 static关键字修饰变量,那么该变量就只能在本文件中修改,其他文件无法使用extern获取变量

2.static

static 既可以修饰全局变量,又可以修饰局部变量。

修饰全局变量

使用之前的例子,在JJExtern的 NSString *flag = @"JJExtension"; 前面加 static,如下

///> JJExtern.h

#import

static NSString *flag = @"DDExtension";

@interface JJExtern : NSObject

@end

再次运行main函数 编译会报错

1044e13bf5d1

note_staticAbout_01.png

所以只要在全局变量前加static,那么这个全局变量的作用域就会缩小到当前文件,外界就不能访问了

总结:

static修饰全局变量,保证全局变量安全,外界不可以访问与修改,作用域仅限于当前文件。

修饰局部变量:

代码:

///> main.m

void test() {

static int a = 0;

a++;

NSLog(@"a = %d", a);

}

int main(int argc, const char \* argv\[\]) {

@autoreleasepool {

for (int i = 0; i<3; i++) {

test();

}

}

return 0;

}

/** 输出结果:

* 2018-12-05 19:20:55.494405+0800 tesy[11959:2261816] a = 1

* 2018-12-05 19:20:55.499893+0800 tesy[11959:2261816] a = 2

* 2018-12-05 19:20:55.505727+0800 tesy[11959:2261816] a = 3

*/

修饰局部变量时,作用域仅限于test函数的大括号内,其他地方都不可以使用。test这个函数中如果不添加 static,那么a打印出来永远都是1,因为在运行完此段函数 局部变量a就会被释放。重新执行函数时a++为0+1.

加上static之后的含义就改变了,结果为1,2,3。因为被static修饰的变量只会初始化一次,永远都只有一份内存,所以当第一次调用test函数时a就已经被初始化了,a有一个内存空间并且值为0,第二次调用test函数由于a被static修饰,所以不会再初始化新的值,它会拿到之前的那份内存进行a++操作,就会变成1,以此类推。

总结:

让局部变量只初始化一次

局部变量在内存中只有一份内存

直到程序结束才会被销毁

3. const

const的作用和宏类似,苹果不推荐使用宏定义,推荐使用const,所以在swift中苹果抛弃了宏的使用。

const 和 宏的区别

\ \

const

编译时刻

预编译(在编译前处理)

编译阶段

编译检查

不做检查,不会报编译错误,单纯替换功能,用宏定义的函数会报参数类型错误

会做编译检查,会报编译错误

宏的好处

宏能定义一些函数、方法 例如RGB函数

不能

宏的坏处

使用大量的宏,容易造成编译时间久每次都需要重新替换

使用过多的宏会消耗大量编译时间。

const的作用就是使右边的变量,只可读,不可修改

三段代码理解const

int x = 1;

int y = 2;

const int *px = &x; // 让指针px指向变量x(此时const右边是*p)

px = &y;// 改变指针px的指向,使其指向变量y

*px = 3; // 改变px指向的变量x的值,出错:Read-only variable is not assignable

int x = 1;

int y = 2;

const int *px = &x; // 让指针px指向变量x(此时const右边是*p)

px = &y; // 改变指针px的指向,使其指向变量y

*px = 3; // 改变px指向的变量x的值,出错:Read-only variable is not assignable

int x = 1;

int y = 2;

const int *px = &x;// 让指针px指向变量x(此时const右边是*p)

px = &y; // 改变指针px的指向,使其指向变量y

*px = 3; // 改变px指向的变量x的值,出错:Read-only variable is not assignable

上面的三段代码处理的是基本数据类型,我们知道OC语言是C语言的超集,所以上面部分基本数据类型的处理OC与C一样。

但是我们知道OC是C语言的超集,OC中还有NSString等的数据类型,它们的本质是个结构体,所以在处理指针方面与基本数据类型不同

代码如下:

#import

int main(int argc, const char * argv[]) {

NSString const *name = @"milo";// const修饰*name

NSLog(@"%@",name);// 打印结果“milo”

name = @"vicky";// 在oc中NSString等类的值不是通过*name访问的,而是通过name访问的,这就是和c语言的指针的区别,但还是遵循const右边是谁,谁就只可读的原则。

NSLog(@"%@",name);// 打印结果“vicky”

}

objective-c语言代码

- (void)viewDidLoad {

[super viewDidLoad];

// 定义变量

int a = 1;

// 允许修改值

a = 20;

// const两种用法

// const:修饰基本变量p

// 这两种写法是一样的,const只修饰右边的基本变量b

const int b = 20; // b:只读变量

int const b = 20; // b:只读变量

b = 1; // 不允许修改值

// const:修饰指针变量\*p,带\*的变量,就是指针变量.

// 定义一个指向int类型的指针变量,指向a的地址

int *p = &a;

int c = 10;

p = &c;

// 允许修改p指向的地址,

// 允许修改p访问内存空间的值

*p = 20;

// const修饰指针变量访问的内存空间,修饰的是右边*p1,

// 两种方式一样

const int *p1; // *p1:常量 p1:变量

int const *p1; // *p1:常量 p1:变量

// const修饰指针变量p1

int * const p1; // *p1:变量 p1:常量

// 第一个const修饰*p1 第二个const修饰 p1

// 两种方式一样

const int * const p1; // *p1:常量 p1:常量

int const * const p1; // *p1:常量 p1:常量

}

总结:

const仅仅用来修饰右边的变量(基本数据变量px 指针变量*px)

被const修饰的变量是只读的

4. static、const结合使用

static与const作用:声明一个只读的静态变量

开发使用场景:在一个文件中经常使用的字符串常量,可以使用static与const组合

///> 开发中常用static修饰全局变量,只改变作用域

///> 为什么要改变全局变量作用域,防止重复声明全局变量。

///> 开发中声明的全局变量,有些不希望外界改动,只允许读取。

///> 比如一个基本数据类型不希望别人改动

///> 声明一个静态的全局只读常量

static const int a = 20;

///> staic和const联合的作用:声明一个静态的全局只读常量

///> iOS中staic和const常用使用场景,是用来代替宏,把一个经常使用的字符串常量,定义成静态全局只读变量.

///> 开发中经常拿到key修改值,因此用const修饰key,表示key只读,不允许修改。

static NSString * const key = @"name";

///> 如果 const修饰 *key1,表示*key1只读,key1还是能改变。

static NSString const *key1 = @"name";

5. extern与const联合使用

开发中使用场景:在多个文件中经常使用的同一个字符串常量,可以使用extern与const组合。

原因:

static与const组合:在每个文件都需要定义一份静态全局变量。

extern与const组合:只需要定义一份全局变量,多个文件共享。

全局常量正规写法:开发中便于管理所有的全局变量,通常搞一个GlobeConst文件,里面专门定义全局变量,统一管理,要不然项目文件多不好找。

///> In the header file

extern NSString *const EOCStringConstant;

///> In the implementation file

NSString *const EOCStringConstant = @"VALUE";

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值