Object C 预处理程序

本文介绍了Objective-C中的预处理指令,包括#define用于常量替换,#import导入头文件,条件编译如#ifdef、#ifndef等在不同平台和调试中的应用,以及#undef取消定义。预处理指令在优化代码和跨平台开发中起着重要作用。
摘要由CSDN通过智能技术生成
预处理程序提供了一些工具,使用这些工具更易于开发、阅读、修改程序,也更易于将程序移植到不同的系统中。

一、#define 语句

   用途:给符号名称指定程序常量,它的本质是“替换”。

#define TRUE 1
   定义了名称 TURE 后,它的值即为1。在程序中任何出现TRUE的地方, 预处理程序都会将其替换为预定义的值:1。

   熟悉C语言的童鞋 一定对 #define 不会陌生, 在对常用的常量进行替换时经常会使用到。如:

#define PI 3.1415926
#define BUFFER 256

   前者是对常用常量的替换,后者多用于对数组分配大小,对常量使用预定义名称有助于加强程序的可扩展性。

   下面说一下更高级的定义类型:

    1.首先解释下为什么#define 后面没有分号“;”,注意#define 的本质是替换,如果在结尾处加分号,那么分号同时也会替换到程序中,如:

#define TRUE 1;
//error 赋值, TURE 的值为:“1;”
int y = TRUE;
      除非十分确定需要分号,否则不要在末尾添加分号。

    2.#define 表达式替换:

      a.判断闰年是一个很常见的问题,用预处理实现:

#define IS_LEAP_YEAR(y) y%4==0 && y%100!=0 || y%400==0
if (IS_LEAP_YEAR(y))</span>
.......
      和方法定义不同,这里没有定义参数y的类型,因此执行时仅为字面文本的替换,并没有调用函数。(注意:在定义有参数的名称时,预定义名称和参数列表的左括号之间不允许有空格)。

      这种预定义通常称为“宏”,这个术语经常用于带有一个或多个参数的预定义。

      b.下面这个宏名位 SQUARE,  简单的求参数的乘方:

#define SQUARE(x) x*x
//当调用为:
int y = SQUARE(x+1) ;
       y = x+1*x+1, 显然不是我们想要的结果,所以正确的处理方式:

#define SQUARE (x)*(x)

       这是一个典型的问题。

       c.下面这个宏允许你方便的根据Frantion类动态地创建分数:

#define MakeFract(x,y) ([[Fraction alloc] initWith:x over:y])
//调用
myFract = MakeFract(1,3); //创建分数1/3

         d. 定义一个名为MAX的宏,用于求两个值的最大值: 
 

#define MAX(a,b) ((a)>(b)?(a):(b))

        注意整个表达和自变量都用括号括起来了,目的是确保运算不受参数中运算符优先级的问题影响结果。

        e. 定义一个宏把小写转换为大写:

//判断是不是小写字母:
#define IS_LOWER_CASE(x) ((x)>='a' && (x)<='z')
//小写转大写
#define TO_UPPER(x) (IS_LOWER_CASE(x)?(x)-'a'+'A':(x))

 

#import 语句

   用途:导入头文件,头文件以.h 结尾,其中包含了变量的定义和函数的声明。import “time.h” 表示time.h这个头文件在当前源程序的相同目录下,import <Foundation/Foundation.h> 表示头文件在系统目录下。导入头文件的优势在于可以把定义集中起来,从而确保所有的程序引用相同的值。

   条件编译:

   条件编译常用于创建可以在不同计算机系统上编译运行的程序,它还经常用来开关程序中的各种语句,比如用来输出变量值或者跟中程序执行流程的调试语句。

    a. #ifdef, #endif, #else 和 #ifndef 语句:

       程序有时候必须依靠系统的相关参数,这些参数在不同色设备(iphone, ipad)或者特定版本的操作系统上分别指定。

       简单判别使用设备不同调节参数的例子:

#ifdef IPAD
#   define kImageFile @"loveHD.png"
#else
#   define kImageFile @"love.png"
#endif
       如果前面定义了符号IPAD,如:#define IPAD 1(或者仅仅是 #define IPAD) ,那么kImageFile 定义为@”loveHD.png“。

       有趣的是,编译器也允许使用编译命令的选项在程序编译时为编译器定义名称:

gcc -framwork Foundation -D IPAD program.m 
       这时同在程序中定义了 IPAD。

       在调试程序时,条件编译也很有用:

#ifdef  DEBUG
   NSLog(@“Username=%s, id=%i”, useName, id);
#endif
       只要在程序编译时定义了DEBUG 就可以利用表达式语句显示一系列变量名称。

    b. #if 和 #elif 预处理程序语句:

        #if 预处理语句为控制条件编译提供了更通用的方法。if 语句可以用来检查常量表达式是否为0。如果表达式结果不为0, 则会处理到#else , #elif 或 #endif 为止的所有后续行,否则跳过它们。

        如在Foundation的头文件NSString.h中:

#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
#define NSMaximumStringLength (INT_MAX-1)
#endif
        这里将预定的变量MAC_OS_X_VERSION_MIN_REQUIRED 与预定义变量 MAC_OS_X_VERISON_10_5进行比较,如果程序在MAC OS X 10.5更高版本上编译,就会将一个字符串的最大长度设置为整型最大值减1。

        下面的语句出现在NSObjcRuntime.h 的头文件中,用于分局使用的特定编译器定义NS_INLINE(如果之前未定义):

#if !defined(NS_INLINE)
   #if defined(__GNU__)
      #define NS_INLINE static __inline_attribute_(always_inline)
      #elif defined(__MWERKS) || defined(__cplusplus)
          #define NS_INLINE static inline
      #elif define(__WIN32__)
           #define NS_INLINE static __inline__
      #endif
#endif

     c. #undef 语句

        有些时候需要使一些已经定义的名称成为未定义的,即可以使用#undef 语句:

#undef IPAD
        这样就消除了IPAD的定义,之后的#ifdef IPAD 和 #if defined(IPAD)语句都将判断为FALSE。

总结:使用预处理不仅可以写出优美的代码,而且很多系统的源码都是包含了大量的预处理程序,算是coder的基础本领。


参考书:

Object C 程序设计 (第四版)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值