Objective-C学习总结#2——预处理
来源:互联网 发布:免费的crm软件 编辑:程序博客网 时间:2024/06/01 08:54
Objective-C学习总结#2——预处理
预处理是Objective-C中的特殊命令,这也是OC的C语言特性。在编译器对程序进行编译之前,编译器会对这些预处理命令进行处理,然后讲这些预处理的结果与源程序一起进行编译。
预处理命令有如下两个特征:
- 预处理命令都必须以#开头。
- 预处理命令通常位于程序开头部分。
- Objective-C学习总结2预处理
- 宏定义
- 带参数的宏定义
- 条件编译
- include与import
宏定义
使用#define、和#undef执行宏定义。
#define的作用就是为字符串起一个名字。例如,如下代码:
#define YES 1#define PI 3.1415926
通常来说,宏名称通常会使用所有字母大写的形式。通过宏定义可以使用更有意义的名字代替原有字符串,例如上面使用PI代替了3.1415926。
关于宏定义,有如下注意点。
- 宏定义并不是C语句,因此不要在宏名称与字符串之间使用=进行赋值,而且宏定义也无须使用分号结束。
- 宏定义并不是变量,它甚至不是常量,因此不要尝试对宏名称进行赋值。
- 编译器对宏定义处理就是进行“查找、替换”——将所有出现宏名称的地方替换成该宏对应的字符串,因此,程序员需要自己保证宏定义是正确的。
执行宏定义之后,该宏的作用域为从定义该宏开始,直到源代码结束,如果希望提前结束宏定义,则可以使用如下语句:
#undef 宏名称
带参数的宏定义
除了定义简单的宏之外,还可以在宏定义中使用参数,这就是带参数的宏定义,带参数的宏定义可以定义更灵活的宏。
定义参数宏的语法格式如下:
#define 宏名称(参数列表) 字符串
使用带参数的宏来计算圆面积:
#import <Foundation/Foundation.h>#define PI 3.1415926#define AREA(r) PI * r * rint main(int argc, char * argv[]){ @autoreleasepool{ NSLog(@"请输入圆的半径:"); double radius; scanf("%lg", &radius); //使用宏执行计算 NSLog(@"圆面积:%g", AREA(radius)); }}
条件编译
通常来说,源代码中所有的代码行都会参与编译,最后生成执行性代码。但在有些时候,程序需要根据特点环境进行选择性编译——例如对于特定的设备,只编译设备相关的代码,这就可借助条件编译来完成。
C语言支持两组条件编译指令。
1.#ifdef
、#ifndef
、#else
、#endif
。
2.#if
、#elif
、#else
、#endif
。
使用#ifdef、#ifndef、#else、#endif执行条件编译。
#ifdef
、#ifndef
、#else
、#endif
主要以宏定义为判断条件来对编译进行流程控制。
源程序文件:IfDefTest.m
#import <Foundation/Foundation.h>#define DEBUG //定义DEBUG宏int main(int argc, char * argv[]){ @autoreleasepool{ for(int i=0; i<10; i++){ #ifdef DEBUG NSLog(@"调试输出:i的值为:%d", i); #endif } }}
上述代码使用NSLog()
函数进行调试时,调试语句放在#ifdef
和#endif
之间控制,这表明只有在定义了DEBUG
宏的前提下,才会编译这条调试语句。这样在开发阶段只要保持DEBUG
宏,编译器就会编译这条NSLog( )
语句,运行时将会产生输出;当需要发布该应用是,只要将DEBUG
宏定义删除,编译器将不会编译这条NSLog( )
语句,运行时就不会产生输出。
除此之外,甚至可以在源代码中完全不定义DEBUG
宏,而是在编译时定义DEBUG
宏,使用clang命令编译源程序时可使用-D
选项定义宏。例如,使用如下命令编译程序即可指定DEBUG
宏。
clang -fobjc-arc -framework Foundation -D DEBUG IfDefTest.m
由此可以总结出一条开发技巧:
将调试语句放在
#ifdef
和#endif
之间,以宏定义为判断条件加以控制,当发布应用时只要删除该宏定义就可使得调试语句不再被编译运行,使得开发人员不在需要逐行的删除这些调试语句。
使用#if、#elif、#else、#endif执行条件编译。
#if
、#elif
、#else
、#endif
提供了更通用的条件编译,它可以对指定的表达式进行判断,据表达式的值决定是否要编译指定的语句。
#import <Foundation/Foundation.h>#define AGE 25int main(int argc, char * argv[]){ @autoreleasepool{ #if AGE > 60 NSLog(@"老年人"); #elif AGE > 40 NSLog(@"中年人"); #elif AGE > 40 NSLog(@"青年人"); #else NSLog(@"少年人"); #endif }}
条件编译指令的存在价值
可能有初学者会问一个问题:使用简单的if、else if之类的分支语句完全可以处理这些流程控制,为什么还要使用条件编译指令?
需要记住条件编译的处理时机——它是在编译器执行编译之前进行的预处理。这意味着:如果使用条件编译命令,那么不符合条件的程序语句根本不会被编译,也不会生成可执行指令;如果使用普通的条件分支语句,所有的代码都编译成可执行代码,而程序运行时需要根据条件决定执行哪些语句——这意味着使用普通条件分支语句生成的文件更大,而且执行的效率更低。
简单来说,能用条件编译处理的流程控制(如果分支条件只有数值、常量、宏变量),应该尽量使用条件编译进行处理。
#include与#import
C语言提供了#include
来导入其他源程序,而Objective-C则提供了#import
来导入其他源程序,而且#import
更加好用。
#include
指令的作用非常简单,它就是将指定的源代码插入到当前源代码的指点位置,从而有可能导致重复导入同一源代码。
Objective-C提供的#import
更加智能:大部分时候,#import
的功能和#include
功能相似,但#import
可以帮助程序员判断,避免重复导入的问题。因此,在Objective-C程序中通常推荐使用#import
来导入源代码。
在大部分情况下,导入用户自定义的源程序都是使用双引号来包含源文件的,用于告诉预处理程序到一个或多个路径下(通常首先搜索当前文件所在路径,也可通过Xcode的项目设置来设置预处理程序的搜索路径)搜索指定的源文件。例如,如下语句:
#import "Person.h"
如果将要包含的源程序放在<
和>
之间,则用于告诉系统只在特定的“系统”头文件路径中搜索被导入的文件,而不是在当前路径搜索。如下语句。
#import <Foundation/Foundation.h>
简而言之,如果导入用户自定义的源文件,那么在#import
后使用双引号来包含源文件的文件名;如果要导入系统的源文件,则在#import
后使用<
和>
来包含源文件的文件名。
- Objective-C学习总结#2——预处理
- [学习笔记—Objective-C]《Objective-C 程序设计 第6版》第十二章 预处理程序
- Objective-C基础—预处理程序
- Objective-C 学习笔记 12 预处理程序
- 【IOS 开发学习总结-OC-7.4】objective-c与c语言的预处理
- 《Objective-C学习总结》
- c/c++预处理学习总结
- Objective-C预处理程序
- objective-C [预处理程序]
- objective-c预处理
- Objective—C NSNumber 总结
- Objective-C @property学习总结2
- Objective—C 学习1
- Objective-C 语言学习总结
- Objective-C学习错误总结
- 黑马程序员之ios学习总结——07 C语言的枚举、预处理指令
- [精通Objective-C]预处理器
- 【IOS 开发学习总结-OC-7.5】objective-c 的c语言特性——结构体
- 大数据名词分析
- 公众号编辑器开发,实现编辑器前端页面
- C语言实现顺序表
- 在tomcat里为多个应用配置不同的访问端口
- (14)文件上传
- Objective-C学习总结#2——预处理
- 二维数组根据某个相同的值归类
- CSS3 盒布局
- POJ2255
- 浅谈jquery对象和DOM对象
- 关于引入别人的ASdemo解决gredle版本问题
- 项目优化之部署建议一
- Unity日常踩坑2
- ArrayList参数化