- 12.3 条件编译
- ifdef MAC_OS_X
- define DATADIR“uxn1/data”
- else
- define DATADIR“usr\data”
- endif
- ifdef、#else和#endlif语句的行为和你期望的一样。如果程序编译时,#ifdef行中所指定的符号已经通过#define语句或命令行定义了,那么编译器将处理从此处开始到#else、#elif或#endif的程序段,否则就忽略这个程序段。
- define POWER_PC 1
- define POWER_PC
- ifndef语句与#ifdef在一条线上。这个语句的使用方式类似,只是如果指定的符号没有定义,它就导致程序处理后续行。
- ifdef DEBUG
- endif
12.3 条件编译
Objective-C预处理程序提供了一项名为条件编译(conditional compilation)的功能。
条件编译通常用于创建可以在不同计算机系统上编译运行的程序。它还经常用来开关程序中的各种语句,例如用来输出变量值或跟踪程序执行流程的调试语句。
12.3.1 #ifdef、#endif、#else和#ifndef语句
遗憾的是,程序有时必须依靠系统相关的参数,这些参数需要在不同的处理器(例如,Power PC与英特尔)或特定版本的操作系统(例如,Tiger与Leopard)上分别指定。
如果有大型程序,它对计算机系统的特定硬件和/或软件有很多这样的依赖(应尽可能减少这种依赖性),最终你可能会有许多这样的定义,在程序移植到其他计算机系统时,它们的值不得不更改。
通过利用预处理程序的条件编译能力,能够减少在程序移植过程中不得不更改这些定义的问题,并且能够把每种机器关于这些定义的值结合到程序中。举个简单的例子,如果前面已经定义了符号MAC_OS_X,下面的语句
ifdef MAC_OS_X
define DATADIR“uxn1/data”
else
define DATADIR“usr\data”
endif
就把DATADIR定义为“uxn1/data”,否则就定义为“usr\data”。
这里可以看到,允许在标志预处理语句开始的#符号之后放置一个或多个空格。
ifdef、#else和#endlif语句的行为和你期望的一样。如果程序编译时,#ifdef行中所指定的符号已经通过#define语句或命令行定义了,那么编译器将处理从此处开始到#else、#elif或#endif的程序段,否则就忽略这个程序段。
要为预处理程序定义符号POWER_PC,使用如下语句:
define POWER_PC 1
或者仅仅
define POWER_PC
就足够了。正如你所见,定义的名称之后没有必要出现文本来满足#ifdef检测。编译器还允许使用编译器命令的特殊选项在程序编译时为预编译器定义名称。命令行:
gcc-framework Foundation-D POWER_PC program.m-
为预处理程序定义了名称POWER_PC,它使program.m中的所有#ifdef POWER_PC语句都判断为TRUE(注意,在命令行中,-D POWER_PC必须在程序名称之前键入)。该技术使得不必编辑源程序就可以定义名称。
使用Xcode,通过选择“项目设置”下的“添加用户定义设置”,就可以添加新的预定义名称并指定它们的值。
ifndef语句与#ifdef在一条线上。这个语句的使用方式类似,只是如果指定的符号没有定义,它就导致程序处理后续行。
前面提到过,在调试程序时,条件编译很有用。你可能在程序中嵌入了很多NSLog调用,用于显示中间结果并跟踪执行流程。如果定义了一个特定名称(如DEBUG),通过将这些语句条件编译到程序中,就可以打开它们。例如,只要程序在编译时定义了名称DEBUG,就可以使用如下一系列语句来显示一些变量的值:
ifdef DEBUG
NSLog(@“User name=%s, id=%i\n”,userName, userId);
endif
程序中可能有很多这样的调试语句。无论何时调试这个程序,都能够通过DEBUG使得所有调试语句都编译。当程序已经能正确工作时,就可以不加DEBUG重新进行编译。这样做还可以削减程序大小,因为没有编译所有调试语句。