iOS优化-宏,const以及内联函数

1,312 阅读5分钟

这是我参与8月更文挑战的第16天,活动详情查看: 8月更文挑战

1、何为宏定义?

宏定义是C语言提供的三种预处理功能的其中一种,这三种预处理包括:宏定义文件包含、条件编译。在IOS中我们经常看到很多宏定义的代码,即使是在苹果的官方文档中宏定义也占据很大位置。

2、宏定义的使用

宏定义又称为宏代换、宏替换,简称“宏”。

格式:

#define 标识符 字符串

其中的标识符就是所谓的符号常量,也称为宏名

预处理(预编译)工作也叫做宏展开:将宏名替换为字符串。

掌握概念的关键是。一切以换为前提、做任何事情之前先要换,准确理解之前就要“换”。 即在对相关命令或语句的含义和功能作具体分析之前就要换:

例:

#define Pi 3.1415926

把程序中出现的Pi全部换成3.1415926

说明:

  • (1)宏名一般用大写
  • (2)使用宏可提高程序的通用性易读性,减少不一致性,减少输入错误和便于修改。例如:数组大小常用宏定义
  • (3)预处理是在编译之前的处理,而编译工作的任务之一就是语法检查,预处理不做语法检查。
  • (4)宏定义末尾不加分号;
  • (5)宏定义写在函数的花括号外边,作用域为其后的程序,通常在文件的最开头。
  • (6)可以用#undef命令终止宏定义的作用域
  • (7)宏定义允许嵌套
  • (8)字符串" " 中永远不包含宏
  • (9)宏定义不分配内存,变量定义分配内存。
  • (10)宏定义不存在类型问题,它的参数也是无类型的。

3、宏定义的优缺点

优点:

  • (1)提高了程序的可读性,同时也方便修改
  • (2)提高程序的运行效率,使用带参数的宏定义即可完成函数调用的功能,又能避免函数的岀栈与入栈操作,减少系统开销,提高运行效率
  • (3)宏是由预处理器处理的,通过字符串操作可以完成很多编译器无法实现的功能,比如##链接符

缺点:

  • (1)由于是直接嵌入的,所以代码可能相对多一点
  • (2)嵌套定义过多可能会影响程序的可读性,而且很容易出错
  • (3)带参数的而言,由于是直接替换,并不会检查参数是否合法,存在安全隐患

补充:

预编译语句仅仅是简单的值代替,缺乏类型的检测机制,这样预处理语句就不能享受C++严格的类型检查的好处,从而可能成为引发一系列错误的隐患。

最后引用《C陷进与缺陷》的一句话,对其进行总结:

宏并不是函数,宏并不是语句,宏并不是类型定义

4、常量宏定义替换方案const

const用法:一般常用的字符串定义成const(对于常量字符串苹果推荐我们使用const

5、宏与const的区别:

  • (1)编译时刻不同,宏属于预编译,const属于编译时刻
  • (2)宏能定义代码,const不能,多个宏对于编译会相对时间较长,影响开发效率,调试过慢,const只会编译一次,缩短编译时间。
  • (3)宏不会检查错误,const会检查错误

6、内联函数的介绍

内联函数从源代码层看,有函数结构,而在编译后,却不具备函数性质,内联函数不是在调用时发生控制转移,而是在编译时将函数体嵌入每一个调用处,编译时,类似宏替换,使用函数体替换调用处的函数名,在代码中用inline关键字修饰,在类中声明的成员函数,自动转换为内联函数;

  • 类中的成员函数默认是内联函数(要求成员函数没有循环和递归,当其中存在循环的递归的时候,编译器会将其默认为一个普通函数处理)
  • 内联函数不允许有循环或者递归语句
  • 内联函数的定义必须出现在第一次调用内联函数之前

比如:

#pragma mark 判断设备是否是iPhone X
static inline BOOL iPhoneX() {
    BOOL iPhoneXSeries = NO;
    if (UIDevice.currentDevice.userInterfaceIdiom != UIUserInterfaceIdiomPhone) {
        return iPhoneXSeries;
    }
    if (@available(iOS 11.0, *)) {
        UIWindow *window = [[[UIApplication sharedApplication] delegate] window];
        if (window.safeAreaInsets.bottom > 0.0) {
            iPhoneXSeries = YES;
        }
    }
    return iPhoneXSeries;
}

7、内联函数的优缺点

优点:

  • 有参数类型检测,更加安全
  • 内联函数是在程序运行时展开,而且是进行参数传递
  • inline关键字只是对编译器的一个定义,如果函数本地不符合内联函数的标准,编译器就会将这个函数当作是普通函数

缺点:

  • 因为内联函数是在调用处展开,所以会使代码边长,占用更多内存

8、内联函数与宏的区别

  • 内联函数在运行时可调试,而宏定义不可以
  • 编译器会对内联函数的参数类型做安全检查或自动类型转换,而宏定义则不会
  • 内联函数可以访问类的成员变量,而宏定义则不能

通过以上对比,我们以后在开发中如果定义一个常量字符串可以用const,定义代码就是用宏或者内联函数;