不带参数的宏定义rtse:概要

上传人:今*** 文档编号:108090591 上传时间:2019-10-22 格式:DOCX 页数:8 大小:99.86KB
返回 下载 相关 举报
不带参数的宏定义rtse:概要_第1页
第1页 / 共8页
不带参数的宏定义rtse:概要_第2页
第2页 / 共8页
不带参数的宏定义rtse:概要_第3页
第3页 / 共8页
不带参数的宏定义rtse:概要_第4页
第4页 / 共8页
不带参数的宏定义rtse:概要_第5页
第5页 / 共8页
点击查看更多>>
资源描述

《不带参数的宏定义rtse:概要》由会员分享,可在线阅读,更多相关《不带参数的宏定义rtse:概要(8页珍藏版)》请在金锄头文库上搜索。

1、不带参数的宏定义:宏定义又称为宏代换、宏替换,简称“宏”。格式:#define 标识符 字符串其中的标识符就是所谓的符号常量,也称为“宏名”。预处理(预编译)工作也叫做宏展开:将宏名替换为字符串。掌握宏概念的关键是“换”。一切以换为前提、做任何事情之前先要换,准确理解之前就要“换”。即在对相关命令或语句的含义和功能作具体分析之前就要换:例:#define PI 3.1415926把程序中出现的PI全部换成3.1415926说明:(1)宏名一般用大写(2)使用宏可提高程序的通用性和易读性,减少不一致性,减少输入错误和便于修改。例如:数组大小常用宏定义(3)预处理是在编译之前的处理,而编译工作的任

2、务之一就是语法检查,预处理不做语法检查。(4)宏定义末尾不加分号;(5)宏定义写在函数的花括号外边,作用域为其后的程序,通常在文件的最开头。(6)可以用#undef命令终止宏定义的作用域(7)宏定义可以嵌套(8)字符串 中永远不包含宏(9)宏定义不分配内存,变量定义分配内存。2.带参数的宏:除了一般的字符串替换,还要做参数代换格式:#define 宏名(参数表) 字符串例如:#define S(a,b) a*barea=S(3,2);第一步被换为area=a*b; ,第二步被换为area=3*2;类似于函数调用,有一个哑实结合的过程:(1)实参如果是表达式容易出问题#define S(r) r

3、*rarea=S(a+b);第一步换为area=r*r;,第二步被换为area=a+b*a+b;正确的宏定义是#define S(r) (r)*(r)(2)宏名和参数的括号间不能有空格(3)宏替换只作替换,不做计算,不做表达式求解(4)函数调用在编译后程序运行时进行,并且分配内存。宏替换在编译前进行,不分配内存(5)宏不存在类型,也没有类型转换。(6)函数只有一个返回值,利用宏则可以设法得到多个值(7)宏展开使源程序变长,函数调用不会(8)宏展开不占运行时间,只占编译时间,函数调用占运行时间(分配内存、保留现场、值传递、返回值)1、尽量用const和inline而不用#define这个条款最好

4、称为:“尽量用编译器而不用预处理”,因为#define经常被认为好象不是语言本身的一部分。这是问题之一。2、再看下面的语句:#define ASPECT_RATIO 1.653编译器会永远也看不到ASPECT_RATIO这个符号名,因为在源码进入编译器之前,它会被预处理程序去掉,于是ASPECT_RATIO不会加入到符号列表中。如果涉及到这个常量的代码在编译时报错,就会很令人费解,因为报错信息指的是1.653,而不是ASPECT_RATIO。如果ASPECT_RATIO不是在你自己写的头文件中定义的,就会奇怪1.653是从哪里来的,甚至会花时间跟踪下去。这个问题也会出现在符号调试器中,因为同样

5、所写的符号名不会出现在符号列表中。解决这个问题的方案很简单:不用预处理宏,定义一个常量:const double ASPECT_RATIO = 1.653;这种方法很有效。但有两个特殊情况要注意。首先,定义指针常量时会有点不同。因为常量定义一般是放在头文件中(许多源文件会包含它),除了指针所指的类型要定义成const外,重要的是指针也经常要定义成const。例如,要在头文件中定义一个基于char*的字符串常量,要写两次const:const char * const authorName = Scott Meyers ;可以用const 来定义常量,也可以用#define 来定义常量。但是前者

6、比后者有更多的优点:(1) const 常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误(边际效应)。(2) 有些集成化的调试工具可以对const 常量进行调试,但是不能对宏常量进行调试。2.实现机制宏是预处理命令,即在预编译阶段进行字节替换。const常量是变量,在执行时const定义的只读变量在程序运行过程中只有一份拷贝(因为它是全局的只读变量,存放在静态存储区的只读数据区。当你声明该量为常量,即告诉程序和编译器,你不希望此量被修改。 程序的实现,为了保护常量,特将常量都放在受保护的静态

7、存储区内。凡是试图修改这个区域内的值,都将被视为非法,并报错。 这不能理解为凡是字符串都是放在静态存储区域的。这个跟数据类型没有关系,而是这个量是变量还是常量的问题。例如,一个字符串变量就是可以被修改的。 这种静态存储区域的保护机制是由编译器实现的,而非存储该值的内存的电器属性。换言之,实质上内存永远都可以被用户随意修改,只是编译器给用户的代码注入了一些自己的保护代码,通过软件手段将这段内存软保护起来。这种保护在汇编级别可以轻松突破,其保护也就无效了。)。3.用法区别define宏定义和const常变量区别:1.define是宏定义,程序在预处理阶段将用define定义的内容进行了替换。因此程

8、序运行时,常量表中并没有用define定义的常量,系统不为它分配内存。const定义的常量,在程序运行时在常量表中,系统为它分配内存。2.define定义的常量,预处理时只是直接进行了替换。所以编译时不能进行数据类型检验。const定义的常量,在编译时进行严格的类型检验,可以避免出错。3.define定义表达式时要注意“边缘效应”,例如如下定义:#define N 2+3 /我们预想的N值是5,我们这样使用N,int a = N/2; /我们预想的a的值是2.5,可实际上a的值是3.5原因在于在预处理阶段,编译器将 a = N/2处理成了 a = 2+3/2;这就是宏定义的字符串替换的“边缘效

9、应”因此要如下定义:#define N (2+3)。const定义表达式没有上述问题。const定义的常量叫做常变量原因有二:const定义常量像变量一样检查类型;const可以在任何地方定义常量,编译器对它的处理过程与变量相似,只是分配内存的地方不同。1.Objective-C中声明常量使用关键字const。如:const double PI = 3.1514;2.Objective-C中变量可以分为成员变量、局部变量和全局变量(用的很少,尽量不要用)。/-常量/方法一:#define kDetailKey “detail text”#define DOWNLOAD_TIMEOUT 60.0

10、#define degresssToRadian(x) (M_PT*(X)/180.0)这种方法直接使用#define定义函数、字符串和数字,和普通的C/C+一样,唯一的区别是字符串需要在前面加上“”符号。方法二:typedef enumkTagLanguageView = 100,kTagSeriesView,kTagSeriesDetailView,kTagThumbView,kTagVideoView,kTagFullPhotoView,TagSystemViews;使用枚举定义常量,在这里kTagSeriesView等于101,在程序中直接使用kTagSeriesView来表示这个常量

11、,这和C/C+一样。方法三:在.m或者.mm文件中使用静态常量声明,和C/C+使用方法一样,例如:static NSString *BlockColorAlphaComponentKey=blockColorAlphaComponent”;/-变量/1.为了强制一个对象隐藏其数据,编译器限制实例变量范围以限制其在程序中的可见性。但是为了提供灵活性,苹果也让开发者显示设置范围(四选一)。2.四种编译指令如下:private实例变量只能被声明它的类访问。protected实例变量能被声明它的类和子类,所有没有显示指定范围的实例变量都是protected。public实例变量可以在任何地方被访问。p

12、ackge使用modern运行时,一个package实例变量在实现这个类的可执行文件镜像中实际上是public的,但是在外面就是private。OC中的package与C语言中的变量和函数的private_extern类似。任何在实现类的镜像之外想使用这个实例变量都会引发link error。这个类型最常用于框架类的实例变量,使用private太限制,使用protected或者public又太开放。/属性/属性:property:property只不过是给编译器看的一种指令,它可以编译之后自动为你生成相应的getter和setter方法。1.公共属性表示你打算如何使用这一类的对象。2.属性声明

13、是一个指令,它告诉编译器如何为变量生成存取方法。(添加属性声明后,你将了解到有关存取方法的信息)3.id类型是一个通用类型,OC使用id表示任意类型的对象,它可以作为一个占位符表示这是一个不确定的类型的对象或者引用。因此,所有的对象都可以用id来表示。4.编译器指令property可以为一个类声明属性,这是一个偷懒的好方法,用property声明属性相当于同时声明并实现了对应的实例变量的访问器方法。当然,也可以通过指定属性的特性(Attribute)类控制自动生成的访问器方法的行为。5.OC里的实例变量默认都是私有的。私有变量只在类自身和子类的实例方法里可见。6.iOS OC声明变量在inte

14、rface括号中和使用proper的区别:方式一:直接在interface中的大括号中声明。interface MyTest:NSObjectNSString *mystr;方式二:直接用property声明interface MyTest:NSObjectproperty(strong,nonatomic)NSString *mystr;随后在.m文件中synthesize mystr = _myStr;(也可以在.m文件中不加synthesize)区别:方式一声明的成员变量是只能在自己类内部使用,而不能在类的外部使用(就是通过类名.点的方式显示不出来。)。方式二可以在类的外部访问,也可以在

15、类的内部通过下划线+变量名或者self.变量名的方式访问。苹果开发模板推荐的是方式二。7.OC是C的严格父集,C能做的事情OC中都能做。属性实际上一个setter方法和一个getter方法,所有对实例变量的访问都是如此,通过setter方法设置值,通过 getter方法获取值你没有必要去优化没有必要优化的东西,你要优化的是很花时间的东西,而访问实例变量不会花太多时间。8.h是共有的API.m是私有的API以及你所有的实现。所有指针要么是强的,要么是弱的,因为OC需要知道怎样处理内存和堆。强表示保持这个的存储,在堆中,保持这个所指的东西7.plist:属性配置文件,基于XML格式,也扮演了一部分定义UI的角色,Xcode在编译的时候会读取里面的配置信息。8.类的声明提供了这个类和程序员之间的接口,类的声明即接口,其实现代码才是真正

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 高等教育 > 大学课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号