OC基础9:预处理程序
"OC基础"这个分类的文章是我在自学Stephen G.Kochan的《Objective-C程序设计第6版》过程中的笔记。
1、 关于#define语句:
(1)、#define语句的用途就是给某个符号名称指定一个程序要用到的常量,比如:
#define TRUE 1
这个语句的意思就是把TRUE指定为1,那么后续的程序中如果需要用到1来做判断或者计算,就可以直接使用TRUE这个符号名称了;
(2)、预定义名称不是变量,所以不能在程序过程中给它赋值,不能改变它的值;
(3)、注意#define语句没有用到等号,也不需要分号结尾,如果结尾加上分号的话,那么这个常量的值就会变成你想要的值和一个分号的合并了,即是这个分号也会被和值同时替换到这个预定义名称中;
(4)、#define语句一般写在程序开始的地方,在#import和include语句后面,但是其实它可以出现在程序的任何位置,只要出现在程序引用它的位置之前即可;
(5)、预定义名称和变量不同,它没有局部作用域这个概念,你可以在程序中任何位置使用你定义过的预定义名称。一般把它放在头文件中,以便在多个源文件中使用它们;
(6)、使用预定义名称来代替常量值,这样增加了程序的可读性,能清晰地看到某个常量的含义以及它的用途。同时如果使用了这种方法定义常量,然后在程序中发现这个常量出错了,那么你只需要修改#define语句,而不需要整个程序去查找这个常量出现的地方并一个一个修改;
(7)、一般来说预定义名称有两种命名习惯:一种是全部字母都大写,比如(1)的例子,一种是以k开头,比如(1)的预定义名称也可以写作kTrue。
2、其实编译器在处理预定义名称的时候,所做的仅仅是简单的查找替换,编译过程中把所有的预定义名称替换成所定义的值;
3、在#define语句中还可以出现表达式,比如这个例子是合法的:
#define TWO_PI 2.0*3.1415926
也可以出现关系运算符,比如这个例子也是合法的:
#define AND &
4、预定义的值本身可以引用另一个预定义的值,比如:
#define PI 3.1415926
#define TWO_PI 2.0*PI
这种情况是合法的,设置把这个两个语句的顺序颠倒过来,也是合法的。
5、如果预定义的名称或者值过长,甚至需要换行写,那么上一行的最后一个字符必须是反斜杠,如下例:
#define XXX ( 2.0 * 5.0 + 31.0 * 7.0 ) \
* 56.0
这个表达式相当于( 2.0 * 5.0 + 31.0 * 7.0 ) * 56.0,注意是可以有空格的。
6、关于宏:
(1)、可以让预定义名称本身带着一个或多个参数,在编译的时候,编译器会自动把参数替换到预定义值的对应位置去。这种预定义成为宏。如下例子:
#define XXX(y) y * 2.0 + y / 5.0
这个预定义允许你在代码中写出n=XXX(5); 这样的语句;
(2)、宏和方法不同,宏的参数是没有类型的,仅仅只是执行字面意义上的替换。同时需要注意,在预定义名称和参数列表的括号之间不允许有空格;
(3)、在定义宏时,参数列表内的每个单独的参数都要打上括号,因为宏只是执行字面意义上的替换,不打括号会有可能出错。如果定义一个宏如下:
#define SQUARE(x) x * x
那么当出现n=SQUARE(y+1)时,这个等式会被替换称n=y+1*y+1,就与本来想求的值不同了。所以这个预定义应该写为:
#define SQUARE(x) ((x) * (x))
全部用括号括起来最保险,因为你有可能会使用SQUARE(x)去和其他数值运算;
(4)、甚至在宏的预定义值中可以调用方法,假设Fraction类有一个初始化的设值方法initWith:over:,那么可以有以下宏定义:
#define MAKE_FRAC(x,y) ([[Fraction alloc] initWith:x over:y])
(5)、宏中允许出现判断语句,比如:
#define MAX(x,y) ((a) > (b)? (a): (b))
(6)、宏中允许出现关系运算符,比如:
#define IS_LOWER_CASE(x) ((x)>=’a’ && (x)<=’z’)
(7)、甚至可以在宏中进行字符从小写到大写的转换,如下例子:
#define TO_UPPER(x) (IS_LOWER_CASE(x)? (x)-‘a’+’A’: (x))
7、可以把所有要用到的预处理定义收集到单独一个h文件中,然后在程序中使用#import把它引入进来。一般使用双引号引入。
8、使用双引号引入文件,系统会在包括当前目录在内的多个目录查找引入文件;把文件名放在尖括号里面,会导致系统只在“特殊”的系统文件目录中查找包含文件。
9、关于几个条件编译语句:
(1)、有时候系统需要使用到硬件的类型来作为参数,比如某个页面在iPad和iPhone上的显示可能就会不同,需要显示不同尺寸的图片,那么此时就需要判断系统的某些参数。
假设在一个iPad程序中已做了以下定义:
#define IPAD 1
那么可以使用条件编译语句进行如下判断来选择要显示那张图片:
#ifdef IPAD
# define kImageFile @”xxxIPad.png”
#else
# define kImageFile @”xxx.png”
#endif
这里就使用了#ifdef、#else和#endif这三个条件编译语句进行了判断;
(2)、同时可以注意到(1)中,#define语句在井号和define之间可以出现空格;
(3)、另外还有#if和#elif两种语句,if语句用来判断常量表达式是否为0;
10、最后还有一个#undef语句,这个语句可以将一些已经定义过的名称消除掉,恢复到未定义的状态;
OC基础9:预处理程序的更多相关文章
- 【OC基础语法考试】
OC基础语法已经全部学完,但是这些知识只是最基础的,还有很多高级知识,这个可能需要后面慢慢的去学习才能体会到.接下来我会总结前面的OC基础语法,如果大家发现有什么不正确的地方,请指正,小弟是新生,多请 ...
- iOS 阶段学习第11天笔记(OC基础知识)
iOS学习(OC语言)知识点整理 一.OC基础知识 1)#import 用于导入头文件,预处理阶段加载引用,只加载一次. 2)OC 依赖于Foundation框架下的头文件Foundation.h, ...
- OC基础笔记目录
OC基础(1) Objective-C简介 OC和C对比 第一个OC程序 面向对象思想 OC基础(2) 类与对象 类的设计 第一个OC类 对象方法的声明和实现 类方法的声明和实现 OC基础(3) 对象 ...
- OC基础 文件管理
OC基础 文件管理 1.文件管理类NSFileManager对象的创建: NSFileManager *fm = [NSFileManager defaultManager]; 2.文件操作: (1 ...
- OC基础 NSDate
OC基础 NSDate #import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @auto ...
- OC基础 NSData
OC基础 NSData 1.NSString转NSData //NSString转NSData NSString *string = @"abcd12345"; NSData *d ...
- OC基础 代理和协议
OC基础 代理和协议 1.协议 (1)oc语言中得协议:一组方法列表,不需要我们自己实现,由遵守协议的类来实现协议所定制的方法. (2)协议的使用步骤:制定协议-->遵守协议-->实现协议 ...
- OC基础 内存管理
OC基础 内存管理 我们所了解的c语言内存管理,如下: (1)c语言的内存分配:char *p = (char*)malloc(100*sizeof(char)); (2)c语言的内存释放:free ...
- OC基础 类的三大特性
OC基础 类的三大特性 OC的类和JAVA一样,都有三大特性:继承,封装,多态,那么我们就来看一下OC中类的三大特性. 1.继承 继承的特点: (1)子类从父类继承了属性和方法. (2)子类独有的属 ...
随机推荐
- OpenGL进阶(十一) - GLSL4.x中的数据传递
in out 对于 vertex shader,每个顶点都会包含一次,它的主要工作时处理关于定点的数据,然后把结果传递到管线的下个阶段. 以前版本的GLSL,数据会通过一些内建变量,比如gl_Vert ...
- LaTex 下编译后不能显示中文,或者中文乱码
在 Sublime Text 中编辑以下文件并保存(第一行的注释很重要),按下 Cammand + B 编译: %!TEX program = xelatex \documentclass[UTF8] ...
- 总结FormsAuthentication的使用
一.先看一下使用FormsAuthentication做登录认证的用法 用法一: FormsAuthentication.SetAuthCookie(username, isPersistent); ...
- magento添加系统sections配置时应注意的事项
(1)只有在新增sections是需要增加对应的acl配置,这个配置可以放在config.xml中或者放在adminhtml.xml中 <adminhtml> <acl> &l ...
- IOS设计模式学习(8)适配器
1 前言 在面向对象软件设计中,有时候我们想把有用而经过精心测试的类,用于应用程序的其他新领域.但是,新功能需要新接口,而新接口与要复用的现有类不一致的情况非常普遍.我们不想为新的接口而重写可靠的类. ...
- hdu 1078 FatMouse and Cheese 记忆化dp
只能横向或竖向走...一次横着竖着最多k步...不能转弯的.... 为毛我的500+ms才跑出来... #include<cstdio> #include<iostream> ...
- java基础之集合List-ArrayList、LinkedList、Vector的差别
PS:本篇博客主要參考jdk的底层源代码.而非自己动手写代码. 请问ArrayList.LinkedList.Vector的差别 ①ArrayList底层实际上是採用数组实现的(而且该数组的类型的Ob ...
- linux中curl命令
linux curl是一个利用URL规则在命令行下工作的文件传输工具.它支持文件的上传和下载,所以是综合传输工具,但按传统,习惯称url为下载工具. 一,curl命令参数,有好多我没有用过,也不知道翻 ...
- php.ini中最好禁止的一些函数
phpinfo() 功能描述:输出 PHP 环境信息以及相关的模块.WEB 环境等信息. 危险等级:中 passthru() 功能描述:允许执行一个外部程序并回显输出,类似于 exec(). 危险等级 ...
- DataSet转Json 方法
防止忘记,留着备用 /// <summary> /// DATASET转JSON /// </summary> /// <param name="ds" ...