首先,预处理命令他不是一个常量!!!!

我们来看一段代码

#define avatar @"60"if (false) {#define avatar @"80"}NSLog(avatar);

这段代码会输出多少,我们将“avatar”定义为了60,然后在一个永远不会执行的代码里面重新定义了“avatar”为80,if语句中的代码永远不会执行,但是在编译时期,编译器会编译这段代码,而这个时候编译器就会将avatar这个名字替换为@“80”,所以这段代码最后的输出结果就是80。

当然这个时候编译器是会有一个警告的,但是不知道有多少同学会忽略这个警告。或者你会告诉我你对警告十分敏感,不会放过他的,但是记住你不是一个人在写代码,可能在别人的页面他给你重新定义了你的define,给你挖了一个大坑,还找不着.........

用const来定义一个常量

const修饰符定义的变量是不可变的,比如说你需要定义一个动画时间的常量,你可以这么做:

static const NSTimeInterval kAnimateDuration = 0.3;

当你试图去修改“ kAnimateDuration”的值的时候,编译器会报错。更加重要的是用这种方法定义的常量是带有类型信息的,而这点则是define不具备的。

也许你已经发现了,如果你像这样定义:

static const NSString * kUserName = @"StrongX";

你是可以修改userName的值的,(说好的常量呢~~~)

首先我们需要确定的是以下两种写法是一样的:

static NSString const * kUserName = @"StrongX";
static const NSString * kUserName = @"StrongX";

也就是说const放在类型前还是类型后是一样的效果。然后不同效果的是下面这种写法:

static NSString * const kUserName = @"StrongX";

const 修饰的是他右边的部分,也就是说:

static NSString const * kUserName = static NSString const (* kUserName )static NSString * const kUserName = static NSString * const (kUserName)

const修饰的是(userName)的时候,不可变的是userName;“*”在C语言中表示
指针指向符,也就是说这个时候userName指向的内存块地址不可变,而内存保存的内容是可变的,我们来做个尝试:

 NSLog(@"内存地址: %x",& kUserName);kUserName = @"superXLX";NSLog(@"内存地址: %x",& kUserName);

以上NSLog会打印*userName指向的内存块地址,而他的输出是:


输出

我们已经发现当我们改变内存的内存的时候他的地址并没有发生改变,也就是说这是符合“const”修饰符的规定的。

而当我们的修饰符是这样的时候:

static NSString * const kUserName = @"StrongX";

我们则无法改变userName的值。

所以当我们需要定义一个不可变的常量的时候 ,我们还是需要将“const”修饰符放到“*”指针指向符后边才对。

一定要同时使用static和const来定义你的变量

上面已经说了const是用来定义一个常量。而static在C语言中(OC中延用)则表明此变量只在改变量的输出文件中可用(.m文件),如果你不加“static”符号,那么编译器就会对该变量创建一个“外部符号”,后果是什么呢?
你可以尝试在不同编译文件中加入以下代码:

NSString * const kUserName = @"StrongX";

可能尽管文件之间并没有相互引用,不存在属性名重复的问题(因为这并不是一个属性,这是一个外部符号),但是编译器还是报错了:

他会告诉你在两个目标文件(.0文件是.m文件编译后的输出文件)有一个重复的符号。(OC中没有类似C++中的名字空间的概念)

所以当你在你自己的.m文件中需要声明一个只有你自己可见的局部变量(k开头)的变量的时候一定要同时使用“static”“const”两个符号。

定义工程中的全局变量

在我们的工程中一定会定义很多全局常量,很多人的做法是会创建一个“ constant.h”文件,在这个文件中用#define声明许多常量,然后将这个头文件引入“pch”文件中,不能说这么做不对,但是如同上面说的那样define可能被修改,当然在命名规范的情况下这种情况很少出现,并且这样做的效率很高。

然而苹果更推荐另外一种做法:"extern",这样做的优势是保持常量绝对不会被修改,并且一定初始化还带有类型信息。

我们在"constants.h"文件中,声明常量

extern NSString *const XUserName;

然后在“constants.m”中定义他:

NSString *const XUserName = @"StrongX";

“extern”定义的常量必须也只能初始化一次,不满足必须以及只能一次的条件那么编译器就会提醒你。在定义全局变量的时候需要要注意你的命名,你可以使用规定好的前缀来命名。

“define”“extern”各有各的优势,不过我个人还是比较推荐使用“extern”.(因为之前在一个工程中被define坑惨了!)。

为什么不要工程中不要随意使用define定义常量相关推荐

  1. python关键字define_在Python中,使用关键字define定义函数。

    在Python中,使用关键字define定义函数. 以下属于生药学有效性评价的是A:有效成分定量分析B:限量检查C:重金属检测D:基原鉴定 若有如下定义和语句:A:7B:12C:8D:9 图示电路中的 ...

  2. python的define_在Python中,使用关键字define定义函数。

    在Python中,使用关键字define定义函数. 答:错 Charles Lamb wrote a series of miscellaneous essays, collected in 1823 ...

  3. C语言中的#define定义常量和宏

    C语言中的define是一个预处理指令. 1.define定义常量        格式为:#define  标识符  常量  , 注意:语句末尾没有":". 2.define定义宏 ...

  4. [C语言]static关键字--#define 定义常量和宏--初识指针--初识C语言(四)

    文章目录 前言 一,static关键字 二,#define 定义常量和宏 三,初识指针 总结 前言 本节主要记录初识C语言第四节内容. 内容包括:static关键字------#define 定义常量 ...

  5. C++ 笔记(07)— 常量(字面常量、const定义常量、constexpr 定义常量、enum 定义常量、define 定义常量)

    在 C++ 中,常量类似于变量,只是不能修改.与变量一样,常量也占用内存空间,并使用名称标识为其预留的空间的地址,但不能覆盖该空间的内容. 常量可以是任何的基本数据类型,可分为整型数字.浮点数字.字符 ...

  6. UIKIT_EXTERN和define定义常量

    看过我其他的博客的人都知道,我喜欢用define定义常量,最近看了一个开源的轮子,使用UIKIT_EXTERN这个定义的常量,了解了一下,发现使用宏定义的常量会在内存中临时开辟一份内存空间,而使用UI ...

  7. #define 定义常量和宏,指针和结构体

    目录 #define 定义常量和宏 #define 定义常量 #define 定义宏 指针 内存 指针变量的大小 结构体 #define 定义常量和宏 #define 定义常量 在变量和常量2,#de ...

  8. define定义常量和宏 以及 寄存器关键字register

    在C语言中,# 指的是预处理指令.像#define就是在main函数之前预先进行定义. define定义常量 这里定义了常量NUM,我们知道数组固定下标值必须是常量,这也进一步说明了这里define定 ...

  9. C语言 define 定义常量 - C语言零基础入门教程

    目录 一.define 简介 二.define 实战 1.不使用 define 2.使用 define 3.使用 define 优点 三.猜你喜欢 零基础 C/C++ 学习路线推荐 : C/C++ 学 ...

最新文章

  1. 开启Web金库:互联网业务成功之道——前言
  2. 软件相关模块与ansible剧本
  3. VS2019错误提示:_CRT_SECURE_NO_WARNINGS的解决方法
  4. Jquery中设置表格的悬浮和选中时行的背景颜色
  5. 在vlan2用计算机名访问,计算机是如何访问一个网页的?vlan间如何实现通信?
  6. sql优化学习(一)
  7. php 企业微信指令回调借款_php处理微信支付回调改变订单支付状态的代码
  8. linux文本模式无法打字,文本终端模式下中文输入法(Fcitx)配置(openSUSE Leap 42.1)...
  9. Bailian2693 最远距离【序列处理】
  10. 批处理批量更改文件名并排序
  11. 拓端tecdat|R语言中GLM(广义线性模型),非线性和异方差可视化分析
  12. H5如何调用手机摄像头?
  13. SparkSQL Analyzed实例源码解析
  14. php下载列表如何实现,phpcms v9 列表页直接下载功能代码实现
  15. 【前端】Axios完全使用指南
  16. IEEE 802.3av 10Gbits EPON 中文翻译(一)
  17. 国外推荐:计算机专业人士必读
  18. Android 学习笔记之九 下拉刷新
  19. 不要轻易当舔狗,除非你想当技术型舔狗
  20. 网站的配色应该如何做

热门文章

  1. 2.利用gradle启动项目
  2. 超惊艳改装 iPad变全息裸眼3D投影机
  3. 小雏鸟的成人式 3(黑心店主)
  4. php工作审批流程,审核流程_POSCMS_PHP开源_迅睿CMS系统
  5. 华为G520联通版 第三方CWM Recovery刷机系统 可充电可U盘模式
  6. [古诗词欣赏]--柳永《蝶恋花》
  7. AT89C51单片机英文说明书
  8. python自动化测试视频教程_精品系列-悠悠python自动化测试视频教程
  9. 智能电话机器人,使用Microsoft语音识别技术(Speech sdk)
  10. CRMEB-PRO单商户多门店来了