个性化阅读
专注于IT技术分析

Objective-C预处理器用法 – Objective-C开发教程

上一章Objective-C开发教程请查看:Objective-C使用结构体

Objective-C预处理器不是编译器的一部分,而是编译过程中的一个独立步骤。简单地说,Objective-C预处理器只是一个文本替换工具,它指示编译器在实际编译之前进行必要的预处理。我们将把Objective-C预处理器称为OCPP。

所有预处理器命令都以一个磅符号(#)开头。它必须是第一个非空字符,为了可读性,预处理指令应该从第一列开始。下面列出了所有重要的预处理器指令:

编号指令和解释
1#define
替换预处理宏
2#include
从另一个文件插入特定的标头
3#undef
取消预处理宏的定义
4#ifdef
如果定义了该宏,则返回true
5#ifndef
如果未定义此宏,则返回true
6#if
测试编译时条件是否为真
7#else
另一个选项是#if
8#elif
在一个语句中使用#else和#if
9#endif
预处理结束条件
10#error
在stderr上打印错误消息
11#pragma
使用标准化的方法向编译器执行特殊的命令

预处理器的例子

分析下面的例子来理解各种指令。

#define MAX_ARRAY_LENGTH 20

这个指令告诉OCPP将MAX_ARRAY_LENGTH的实例替换为20。使用#define作为常量来增加可读性。

#import <Foundation/Foundation.h>
#include "myheader.h"

这些指令告诉OCPP从Foundation框架中获取foundation.h,并将文本添加到当前源文件中。下一行告诉OCPP从本地目录获取myheader.h并将内容添加到当前源文件。

#undef  FILE_SIZE
#define FILE_SIZE 42

这告诉OCPP取消对现有文件大小的定义,将其定义为42。

#ifndef MESSAGE
   #define MESSAGE "You wish!"
#endif

这告诉OCPP只有在消息尚未定义时才定义消息。

#ifdef DEBUG
   /* 这里是调试语句 */
#endif

这告诉OCPP,如果定义了调试,则执行所包含的语句。如果在编译时将-DDEBUG标志传递给gcc编译器,这将非常有用。这将定义调试,因此你可以在编译期间动态地打开和关闭调试。

预定义的宏

ANSI C定义了一些宏,虽然每个宏都可以用于编程,但是不应该直接修改预定义的宏。

编号宏定义和解释
1__DATE__
当前日期作为“MMM DD YYYY”格式的文字字符
2__TIME__
当前时间为字符文字在“HH:MM:SS”格式
3__FILE__
它包含当前文件名作为字符串文字。
4__LINE__
它以十进制常量的形式包含当前行号。
5__STDC__
当编译器符合ANSI标准时定义为1。

下面是一个使用例子:

#import <Foundation/Foundation.h>

int main() {
   NSLog(@"File :%s", __FILE__ );
   NSLog(@"Date :%s", __DATE__ );
   NSLog(@"Time :%s", __TIME__ );
   NSLog(@"Line :%d", __LINE__ );
   NSLog(@"ANSI :%d", __STDC__ );
   
   return 0;
}

预处理器运算符

Objective-C预处理器提供以下操作符来帮助你创建宏:

宏延续(\)

宏通常必须包含在一行中,宏延续操作符用于延续对于单个行来说太长了的宏。例如−

#define  message_for(a, b)  \
   NSLog(@#a " and " #b ": We love you!")

字符串化 (#)

当在宏定义中使用字符串化或数字化操作符(‘#’)时,它将宏参数转换为字符串常量。此操作符只能用于具有指定参数或参数列表的宏。例如−

#import <Foundation/Foundation.h>

#define  message_for(a, b)  \
   NSLog(@#a " and " #b ": We love you!\n")

int main(void) {
   message_for(Carole, Debra);
   return 0;
}

标记粘贴(##)

宏定义中的标记粘贴操作符(##)组合了两个参数。它允许将宏定义中的两个独立标记连接到单个标记中。例如−

#import <Foundation/Foundation.h>

#define tokenpaster(n) NSLog (@"token" #n " = %d", token##n)

int main(void) {
   int token34 = 40;
   
   tokenpaster(34);
   return 0;
}

defined()运算符

预处理程序defined操作符用于常量表达式中,以确定标识符是否使用#define定义。如果定义了指定的标识符,则该值为true(非零)。如果没有定义符号,则该值为false(0)。定义的运算符如下所示:

#import <Foundation/Foundation.h>

#if !defined (MESSAGE)
   #define MESSAGE "You wish!"
#endif

int main(void) {
   NSLog(@"Here is the message: %s\n", MESSAGE);  
   return 0;
}

参数化的宏

OCPP的强大功能之一是能够使用参数化宏模拟函数。例如,我们可以用一些代码来对一个数求平方,如下所示

int square(int x) {
   return x * x;
}

我们可以使用以下宏重写上述代码

#define square(x) ((x) * (x))
赞(0)
未经允许不得转载:srcmini » Objective-C预处理器用法 – Objective-C开发教程

评论 抢沙发

评论前必须登录!