宏与const
宏的介绍
宏,是一种批量处理的称谓,简单来说就是根据定义好的规则替换一定的文本
替换过程在程序编译期间,因此大量使用宏会造成编译时间过长
安全性
宏在替换过程不进行安全性检查,因此要注意“边缘效应”
举个例子
#define N 1+2
NSInteger a = N/2;
//期望结果 a = 1.5 实际结果 a = 2
原因是在替换过程中 a = N/2 = 1+2/2 = 2
,因此我们在定义宏时建议加上括号来表示为一个整体
宏的分类
可以分为对象宏和函数宏,也可分为带参数的宏和不带参数的宏
-
对象宏
#define AGE 20
-
函数宏
#define MAX(X,Y) ((X)>(Y)?(X):Y))
注意这里就是注意了边缘效应,我们加上括号
宏的用法
-
字符化
如果想直接使用字符串可以添加一个“#”
#define STR(x) #x NSLog(@"str:%s",STR(aaa)); //输出结果:str:aaa
使用“##”进行连接
#define function(name) +(instancetype)function##name function(get) //即执行functionget
#define PARSER(N) printf("token" #N " = %d\n", token##N) int token64 = 64; int token32 = 32; PARSER(64);//用来打印token64 PARSER(32);//用来打印token3 //输出结果 //token64 = 64 //token32 = 32
-
使用ARC和MRC
#if __has_feature(objc_arc) // ARC #else // MRC #endif
-
带参数的宏在调用时不仅要宏展开,还要用实参去替换形参
一般形式
#define 宏名(形参表) 字符串
常见的就是NSLog,在项目开发中,我们会在许多时候用到NSLog来打印参数查看结果,但是发布的时候又不希望有这些NSLog函数,但一个庞大的项目一个个删除也是不现实的,因此我们就可以用到自定义NSLog
#ifdef DEBUG #define LRLog(...) NSLog(@"%s 第%d行 \n %@\n\n",__func__,__LINE__,[NSString stringWithFormat:__VA_ARGS__]) #else #define LRLog(...) LRLog(@"111"); //打印结果main 第25行 111
__VA_ARGS__
: 至少传一个参数##__VA_ARGS__
: 随便传几个参数
const介绍
const为只读关键字,一旦用来确定内容或者指针后在使用的时候是不可以改变其已经确定的内容或指针
const用法
基本数据类型
// 这两种情况,是一样的.
// 只读常量
int const a = 10;
const int b = 20;
const与指针类型
const位置不同对应的限制也不同
举个例子
当在最前面的时候,表示指针不允许被改变,值可以改变
const NSString *namePoint1 = @"test";
在中间的时候,也是指针不允许被修改,值可以改变
NSString const *namePoint2 = @"test";
在最后的时候,代表值不能改变,指针可改变(最常用)
NSString * const namePoint3 = @"test";
经验总结
const右边最近的内容不可以被改变
最简单的方法就是去掉类型查看
const *namePoint1 = @"test";
const *namePoint2 = @"test";
* const namePoint3 = @"test"; //const namePoint3不可变,值
const可以节省空间,避免不必要的内存分配,编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高
总结
宏的优点
- 提高了程序的可读性,同时也方便进行修改,用户只需要在一处定义,多处使用,修改也只需要修改一处
- 提高程序的运行效率:使用带参的宏定义既可完成函数调用的功能,又能避免函数的出栈与入栈操作,减少系统开销,提高运行效率,如果有一个函数会在工程中频繁使用,可以考虑一下宏定义
宏的缺点
- 宏数量过多会导致编译时间相对较长
- 没有安全性检查
宏与const的区别
#define和const常量都可用来修饰常量
-
编译器处理方式不同
- 宏是在预处理阶段展开
- const是在编译运行阶段使用
-
类型和安全检查不同
- 宏仅仅只是展开,有多少地方使用,就展开多少次,不分配内存
- const会在内存中分配(堆栈都可以),是全局的,内存只有一份,const会检查错误
-
能否定义代码
- 宏可以定义代码
- const不能定义代码
-
编译时间
-
宏数量过多会导致编译时间相对较长
-
const只会编译一次,缩短编译时间
-
在开发中,通常定义一个常量字符串用const,定义代码就用宏
参考博客