文章起因:
由于本人在项目中一直不清楚什么时候使用define 定义常量,什么时候使用宏,来定
义一些字符串啊,数字啊这些变量,所以就有了这篇文章的所在
首先两者的定义与实现
一.define(宏定义)
#define
语法称之为预处理命令。#define
声明主要用于将常量(或字符串)赋予有意义的名字,比如当你在编写一个日历程序时,可以定义:
#define MONTHS_PER_YEAR 12
Tips:
1.通常情况下,习惯将预处理的常量名全大写,单词之间用下划线隔开
(与正常变量区分)。
2.如果是定义常量,若这个常量的适用范围局限于.m,那么习惯性在常量名前
加k,若常量在类之外可见,则通常以类名为前缀
预处理代码起的作用实际上相当于在编译之前!!!
预处理代码起的作用实际上相当于在编译之前!!!
预处理代码起的作用实际上相当于在编译之前!!!
重要事情说三遍。也就是说宏使用过多会增加编译时间,
而一个常量在栈中开辟空间是很高效的。
在整个代码中进行了一次“搜索、替换”功能.通常情况下不管是声名字符串还是函数其作用主要有两个:
个人认为使用宏有一下好处:
1.增强代码可读性
2.方便全局使用和修改一些方法和参数
3.增强复用性
(以上为个人总结,标准答案见第二大标题:两者的区别 中的那篇引文博客)
二.const(定义常量)
const 如果是声明常量,仅仅是想要在.m文件中使用,那么一定要同时使用static 和const来声明,若不加系统在编译时会自动为它加一个extern (外部符号),此时,若另一个编译单元出现了同名变量就会报错,并且很难查找错误
这是OC程序员最不愿意看到的错误。。。也是很难查找的错误,跟修改已经创建的类的文件名的错误差不多。
结合经验,和在网上查找资料,我个人认为,可以得出以下结论:
- 多用类型常量,少用#define预处理指令(出自《Effective Objective-C》第四条原则)
2.苹果的API中,大多数字符串,也是用以下这种方式(如以Key,style,Type结尾的一些参数)
// Constants.h
FOUNDATION_EXPORT NSString *const MyFirstConstant;
FOUNDATION_EXPORT NSString *const MySecondConstant;
//etc.
// Constants.m
NSString *const MyFirstConstant = @"FirstConstant";
NSString *const MySecondConstant = @"SecondConstant";
或者
extern NSString * const PPRememberMusicList;
extern NSString * const PPLoadMusicAtListLoad;
extern NSString * const PPAfterPlayingMusic;
extern NSString * const PPGotoStartupAfterPlaying;
NSString * const PPRememberMusicList = @"Remember Music List";
NSString * const PPLoadMusicAtListLoad = @"Load music when loading list";
NSString * const PPAfterPlayingMusic = @"After playing music";
NSString * const PPGotoStartupAfterPlaying = @"Go to startup pos. after playing";
两者的区别
网上有关于C++这两个关键字的说明,看文章格式格式应该是来自于C++的一个本书中的,感觉写的相当详细:
来自:@奮 鬥@的专栏的
const常量与define宏定义的区别
因为C++和OC本来就是来自于C所以这里可以直接参考的。
其中本人筛选了其中比较重要的一些比较,是有利于解决本文的初衷问题的:
- const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝(因为是全局的只读变量,存在静态区),而 #define定义的常量在内存中有若干个拷贝
归纳为:使用const定义常量比较好,因为省内存空间
- 提高了效率。 编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高
归纳为:使用const定义常量比较好,因为效率高
- 宏替换只作替换,不做计算,不做表达式求解;
宏预编译时就替换了,程序运行时,并不分配内存。
归纳为:宏定义 定义函数式比较好,因为省内存
还有这一段:
const 与 #define的比较
C++ 语言可以用const来定义常量,也可以用
#define来定义常量。但是前者比后者有更多的优点:
(1) const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误(边际效应)。
(2) 有些集成化的调试工具可以对const常量进行调试,但是不能对宏常量进行调试。
l 【规则5-2-1】在C++ 程序中只使用const常量而不使用宏常量,即const常量完全取代宏常量。
归纳为:const就是比宏牛逼!!!!!(哈哈 常量来说,并不是宏就没用了)
总结问题答案
看到这里问题的答案其实已经很清楚了,而且也解决了这个问题之外的一些问题的答案,让我对C++和内存优化问题上有了进一步的了解!!!
专业总结一万年
const简介:之前常用的字符串常量,一般是抽成宏,但是苹果不推荐我们抽成宏,推荐我们
使用const常量。
编译时刻:宏是预编译(编译之前处理),const是编译阶段。
编译检查:宏不做检查,不会报编译错误,只是替换,const会编译检查,会报编译错误。
宏的好处:宏能定义一些函数,方法。 const不能。
宏的坏处:使用大量宏,容易造成编译时间久,每次都需要重新替换。
2018-6-22 1:50
番外篇
const、static与extern
上面大量讲了const
和define
这两个关键字的作用与区别,分析有些片面。
比如const在修饰一个变量如NSString字符串的时候,是将这个字符串放在栈区,随应用声明周期,因为常量是放在栈区由系统直接分配管理的。
之所以为什么要考虑一个变量的内存问题呢?其实程序员每天在做的工作不仅仅是完成一个代码的编写,更多的是在做一个整体的把控。如何从一个思想到一个能够为人服务的手机软件?
这期间经历的什么其实需要我们考量的。这个些问题我会在一片文章中详谈!我觉得作为一个智者,应该搞清楚自己知道什么不知道什么,才利于前行!
---------致敬那曾经的‘伪程序员’-------自己!-------
const
const 在修饰一份变量的时候,一最简单的理解方式就是,老师拿了一个动物大象模型,给同学讲故事,这个动物的模型将在整个故事过程中充当学生脑海里整个听故事过程中的这个大象,而大象只有一个,在过程中它是不可能被替换的,因为它真实存在,而大象经历了什么,又代表什么是任务设定的,这个是可以定义的;而这个大象它代表了什么将会在这个古故事结束之后,任由他去了。也许他仅仅是个模型,但是,只要在这个故事当中,他就是不可代替的!
所以,一个常量的生命周期就如同显示存在的一个事物,不可被替代的事物,独一无二的事物(如太阳,月亮和星星)也正对应了----常这个字!
不知道说道这里,和我一样经历的你有没有明白些什么!
它随时被申请在内存空间,但永远只有一份!也正是为什么一个程序中,声明两个相同的const常量,会出现上面报错的原因!
static
举一反三,我们可以从字面理解,“静”这个字的含义,之所以是静态,专业术语分析是因为,专门用来修饰局部变量,(因为局部变量是在函数结束的时候就会消失掉),将局部变量的生命周期变为和全局变量的生命周期一样,在程序结束的时候消失!
#专业总结
* 修饰局部变量
* 让局部变量只初始化一次
* 局部变量在程序中只有一份内存
* 并不会改变局部变量的作用域,仅仅是改变了局部变量的生命周期(只到程序结束,这个局
部变量才会销毁)
* 修饰全局变量
* 全局变量的作用域仅限于当前文件
extern
更容易理解在这里不再复述!
网友评论