前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >iOS学习——iOS 宏(define)与常量(const)的正确使用

iOS学习——iOS 宏(define)与常量(const)的正确使用

作者头像
mukekeheart
发布于 2019-09-29 02:32:36
发布于 2019-09-29 02:32:36
1.9K00
代码可运行
举报
运行总次数:0
代码可运行

概述

  在iOS开发中,经常用到宏定义,或用const修饰一些数据类型,经常有开发者不知怎么正确使用,导致项目中乱用宏与const修饰。你能区分下面的吗?知道什么时候用吗?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#define HSCoder @"汉斯哈哈哈"
NSString *HSCoder = @"汉斯哈哈哈";
extern NSString *HSCoder;
extern const NSString *HSCoder;

static const NSString *HSCoder = @"汉斯哈哈哈";

const NSString *HSCoder = @"汉斯哈哈哈";
NSString const *HSCoder = @"汉斯哈哈哈";
NSString * const HSCoder = @"汉斯哈哈哈";

当我们想全局共用一些数据时,可以用宏、变量、常量

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//宏
#define HSCoder @"汉斯哈哈哈"

//变量
NSString *HSCoder = @"汉斯哈哈哈";

//常量,四种写法
static const NSString *HSCoder = @"汉斯哈哈哈";
const NSString *HSCoder = @"汉斯哈哈哈";
NSString const *HSCoder = @"汉斯哈哈哈";
NSString * const HSCoder = @"汉斯哈哈哈";

宏、变量、常量之间的区别

  • 宏:只是在预处理器里进行文本替换,没有类型,不做任何类型检查,编译器可以对相同的字符串进行优化。只保存一份到 .rodata 段。甚至有相同后缀的字符串也可以优化,你可以用GCC 编译测试,"Hello world" 与 "world" 两个字符串,只存储前面一个。取的时候只需要给前面和中间的地址,如果是整形、浮点型会有多份拷贝,但这些数写在指令中。占的只是代码段而已,大量用宏会导致二进制文件变大
  • 变量:共享一块内存空间,就算项目中N处用到,也不会分配N块内存空间,可以被修改,在编译阶段会执行类型检查
  • 常量:共享一块内存空间,就算项目中N处用到,也不会分配N块内存空间,可以根据const修饰的位置设定能否修改,在编译阶段会执行类型检查

  我们来看一段代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#define avatar @"60"
    if (false) {
        #define avatar @"80"
    }
    NSLog(avatar);

  这段代码会输出多少,我们将“avatar”定义为了60,然后在一个永远不会执行的代码里面重新定义了“avatar”为80,if语句中的代码永远不会执行,但是在编译时期,编译器会编译这段代码,而这个时候编译器就会将avatar这个名字替换为@“80”,所以这段代码最后的输出结果就是80。   当然这个时候编译器是会有一个警告的,但是不知道有多少同学会忽略这个警告。或者你会告诉我你对警告十分敏感,不会放过他的,但是记住你不是一个人在写代码,可能在别人的页面他给你重新定义了你的define,给你挖了一个大坑,还找不着.........

  所以还是尽量使用const,看苹果api也是使用常量多点,如下图:

const的用法

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
static const NSTimeInterval kAnimateDuration = 0.3;

  当你试图去修改“ kAnimateDuration”的值的时候,编译器会报错。更加重要的是用这种方法定义的常量是带有类型信息的,而这点则是define不具备的。也许你已经发现了,如果你像如下这样定义,你是可以修改userName的值的,(说好的常量呢~~~)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
static const NSString * kUserName = @"StrongX";

  首先我们需要确定的是以下的三种写法中前两种是一样的(可以修改kUserName的内容,也就是说const放在类型前还是类型后是一样的效果),第三种的效果不一样(无法修改kUserName的内容)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
static NSString const * kUserName = @"StrongX";
static const NSString * kUserName = @"StrongX";

static NSString  * const kUserName = @"StrongX";

  需要注意的是const 修饰的是他右边的部分,也就是说:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
static NSString const * kUserName = static NSString const (* kUserName )

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

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
NSLog(@"内存地址: %x",& kUserName);
kUserName = @"superXLX";
NSLog(@"内存地址: %x",& kUserName);

以上NSLog会打印*userName指向的内存块地址,而他的输出如下图,我们已经发现当我们改变内存的内容的时候他的地址并没有发生改变,也就是说这是符合“const”修饰符的规定的。

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
static NSString  * const kUserName = @"StrongX";

extern和static的用法

  在常量定义时我们经常会用到两个关键字,extern和static。那么这两个关键字的具体用法和作用是什么呢?下面我们就一起探究一下。

关键字extern

关键字extern主要是用来引用全局变量,它的原理是先在本文件中查找,查找不到再到其他文件中查找。用“extern”定义的常量必须也只能初始化一次,不满足必须以及只能一次的条件那么编译器就会提醒你。在定义全局变量的时候需要要注意你的命名,你可以使用规定好的前缀来命名。我们一般的用法是在.h文件中用extern申明一个常量名称,表示该常量可以让外部引用,然后在.m文件中对该常量进行初始化。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//在"constants.h"文件中,声明常量:
extern NSString *const XUserName;
代码语言:javascript
代码运行次数:0
运行
复制
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//然后在“constants.m”中定义他:
NSString *const XUserName = @"StrongX";

关键字static

在探讨static的用法之前,我们首先需要了解两个概念:生命周期、作用域。

  • 生命周期:这个变量能存活多久,它所占用的内存什么时候分配,什么时候收回。
  • 作用域:这个变量在什么区域是可见的,可以拿来用的。

static分两种情况:修饰局部变量、修饰全局变量。

1、static修饰局部变量

  • 局部变量:在函数/方法/代码块内声明的变量。它的生命周期、作用域都是在这个代码块内。局部变量 存储在栈区(stack)一旦出了这个代码块,存储局部变量的这个栈内存就会被回收,局部变量也就被销毁。
  • 静态局部变量当用static修饰局部变量时,变量被称为静态局部变量,和全局变量,静态全局变量一样,是存储在‘静态存储区’。存储在 静态存储区 的变量,其内存直到 程序结束 才会被销毁。即,生命周期是整个源程序。

所以,静态局部变量的生命周期是整个源程序,但,作用域是声明它的代码块内

2、static修饰全局变量

  • 当全局变量没有使用static修饰时其存储在静态存储区,直到程序结束才销毁。也就是其作用域是整个源程序。我们可以使用extern关键字来引用这个全局变量。
  • 当全局变量使用static修饰时,其生命周期没有变,依旧是在程序结束时才销毁。但是其作用域变了。现在只限于申明它的这个文件才可见。使用extern关键字无法引用这个全局变量。
  • 全局变量本来是在整个源程序的所有文件都可见,static修饰后,改为只在申明自己的文件可见,即修改了作用域。即如果在.m文件中用static定义了常量,那么就不能在.h文件中使用extern进行外部申明。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//在.m文件中这样定义,则该常量只能在当前.m文件中使用,并且不能再.h文件中使用extern进行外部申明使用
static NSString * const kUserName = @"userName";

此外,常量的定义默认是extern类型的,上面已经说了const是用来定义一个常量。而static在C语言中(OC中延用)则表明此变量只在改变量的输出文件中可用(.m文件),如果你不加“static”符号,那么编译器就会对该变量创建一个“外部符号”所以如果你在两个互不相关的.m文件中定义了同名的常量,即使这两个文件之间没有任何关联,但是编译的时候会报错。报错类型如下

他会告诉你在两个目标文件(.0文件是.m文件编译后的输出文件)有一个重复的符号。(OC中没有类似C++中的名字空间的概念) 所以当你在你自己的.m文件中需要声明一个只有你自己可见的局部变量(k开头)的变量的时候一定要同时使用“static”和“const”两个符号。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-08-22 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
行业资讯 | 区块链或将真正迎来高速发展期!
作为这两年最为热门的创业领域和科技话题,区块链引发了许多的争论。支持者称它将会是第四次技术革命,而批判者则认为它是泡沫的代名词。数字经济之父、《区块链革命》作者唐·塔斯考特表示,区块链标志着人类有史以来有了一张“价值的互联网”。一切有价值的东西可以通过一个体系以一种私密并且安全的方式进行点对点的管理、交易和传输。美国科学院院士、中国科学院外籍院士张首晟认为,未来的信息技术有三大模块:量子计算、人工智能和区块链。互联网建筑的是相互之间信息的交流,但是区块链是相互之间价值的交换。两位区块链领域的权威人士都肯定区块链作为新技术的价值。业内人士介绍:在供应链金融等领域,区块链的应用已有很多,预计将在2018到2019年之间将会出现一批区块链应用场景和技术。
区块链领域
2018/07/23
4670
行业资讯 | 区块链或将真正迎来高速发展期!
chain33架构介绍
应用层:兼容以太坊智能合约,支持发行代币、资产交易、钱包找回,hash锁定等原生能力,同时支持用户可扩展执行器(合约)。共识层:共识算法可插拔,支持POS及DPOS的公链共识、Tendermint及pbft联盟链共识、Raft私链共识、平行链共识等。数据层:数据存储方式支持可扩展,目前支持MPT、MAVL、KVDB、MVCCKVDB多种方式。
用户9361942
2023/02/15
3760
chain33架构介绍
专注区块链底层技术突破,“复杂美”用技术开源推动产业未来
杭州复杂美科技有限公司(以下简称:复杂美)成立于2008年,是一家致力于高性能撮合技术研发的区块链底层技术提供商,专注于区块链撮合系统、区块链清算系统的应用与推广。
用户9361942
2023/04/14
6980
专注区块链底层技术突破,“复杂美”用技术开源推动产业未来
chain33技术特点总结
在区块链多语言版本的SDK中,既支持国际标准,也支持国密标准。支持SM2,SM3,SM4。
用户7358413
2022/03/04
5150
chain33技术特点总结
复杂美chain33区块链BaaS云服务
1. 整体架构 采用模块插件化的设计,模块可插拔,适应多种场景。 应用层 EVM虚拟机, WASM虚拟机,GO语言原生合约以及JVM虚拟机(研发完成,测试中)共识层 支持POS,DPOS以及POS33的公链共识、Tendermint及pbft联盟链共识、Raft私链共识、平行链共识等。数据层 数据存储方式支持可扩展,目前支持MPT、MAVL、KVDB、MVCCKVD...
用户7358413
2022/02/08
7020
复杂美chain33区块链BaaS云服务
区块链BaaS云服务(15)复杂美chain33
【摘要】 1. 整体架构 采用模块插件化的设计,模块可插拔,适应多种场景。 应用层 EVM虚拟机, WASM虚拟机,GO语言原生合约以及JVM虚拟机(研发完成,测试中)共识层 支持POS,DPOS以及POS33的公链共识、Tendermint及pbft联盟链共识、Raft私链共识、平行链共识等。数据层 数据存储方式支持可扩展,目前支持MPT、MAVL、KVDB、MVCCKVD...
用户7358413
2021/06/30
6860
Chain33区块链底层技术特色
Chain33开发者平台,是一个易上手、高性能、稳定、安全的区块链底层系统,可供开发公链、联盟链及私链,并在业内首创平行链架构及模块化体系。
用户9361942
2022/01/10
7240
Chain33区块链底层技术特色
33复杂美区块链核心技术Chain33开发平台系统特点
联盟让开发者一学就会用,一用就能开发部署,是Chain33的首要愿望。Chain33开发者平台部署快捷简单,一个可执行文件,数个配置参数,一行启动命令便可以快速部署一个区块链主链网络及平行链网络。
用户7358413
2022/03/02
4830
33复杂美区块链核心技术Chain33开发平台系统特点
复杂美公司自主研发Chain33 平行链
平行链是Chain33的一大亮点,Chain33是业内第一个提出“平行链”概念,并实现开发应用公链系统。它是在主链基础上搭建的区块链,因此,平行链并不是一个简单的“DAPP应用”,更拥有自己独立的区块链生态。平行链使用主链的共识,结合开放平台的API 和 SDK,就可以开发出自己所需的应用链,非常适合需要建立自己商业生态的中小企业。 构成方面,平行链是由多条底层为Chain33的链组成;主链负责交易清算,而智能合约和虚拟机则从主链上分离放到平行链上独立执行。多条平行链并存可大幅提升区块链的运算效率,平行链之间则通过主链实现链间互联。此外,平行链的交易由自己的节点来验证、校对,不会影响到主链。主链将会保障平行链的安全、稳定,并开放空间给各个平行链存放数据;所有数据在主链上存储以及进行共识,平行链只负责执行。 因此,主链上的数据是最权威、最完整的,平行链依附于主链,同时又保持相对的独立,从而构建了整个区块链网络生态。 每一条平行链都是一个独立的区块链生态,用户可以根据提供的文档自行搭建平行链。即可编写多种智能合约,创建自己的独立钱包、浏览器、dapp,发行数字通证,部署超级节点,甚至可以开发对接其他dapp,拥有很强的拓展性。 经过5年开发,从2018年11月开源至今,Chain33平行链在Github开源社区上的代码提交已超过8000多次,获得众多合作方的认可。目前,Chain33平行链被阿里、百度、360等机构跟进研究;同时还和微软达成合作,登上了微软云的推荐版面, 这意味着更多用户可以更简单地接入到Chain33。
用户7358413
2022/04/12
3690
复杂美公司自主研发Chain33 平行链
元宇宙基础设施:WEB 3.0 chain33 优势分析
使用 Solidity 开发智能合约并部署在 EVM 虚拟机上是目前以太坊生态主流的开发
用户7358413
2022/07/25
3210
元宇宙基础设施:WEB 3.0 chain33 优势分析
元宇宙基础设施:WEB 3.0 chain33 优势分析
使用 Solidity 开发智能合约并部署在 EVM 虚拟机上是目前以太坊生态主流的开发
用户9361942
2023/02/15
2690
元宇宙基础设施:WEB 3.0 chain33 优势分析
20万赚200万,48岁创业者是这样吊打小鲜肉的!
说起吴思进这个名字,想必知道的人并不多,但如果说起他一手建立的33复杂美,干过区块链的都会情不自禁地竖起大拇指。
区块链大本营
2019/03/12
8570
20万赚200万,48岁创业者是这样吊打小鲜肉的!
复杂美公链技术重要特色:平行公链架构
复杂美公链技术Chain33从11月开源至今,获得众多合作方的认可,其中首创的平行公链架构被百度、阿里、360等机构认可并跟进研究,这也说明了平行公链或许是区块链普及应用的重要解决方案之一。
用户9361942
2023/02/03
4550
复杂美公链技术重要特色:平行公链架构
平行链和主链是什么关系?
从私链到联盟链,33复杂美创始人吴思进转变为公链的信仰者。他笃信区块链是一个完全颠覆性的创新,复杂美CEO吴思进将围绕chain33解答我们的疑惑:什么是平行链,和主链之间又有什么关系?
用户9361942
2022/12/07
1.1K0
平行链和主链是什么关系?
复杂美布局私有链、联盟链,阶段性推展迈向公有链
复杂美布局私有链、联盟链,阶段性推展迈向公有链33 复杂美有一项难以被取代的纪录,那就是拥有中国的第一个区块链专利。
用户7358413
2022/03/07
4990
复杂美布局私有链、联盟链,阶段性推展迈向公有链
基于区块链的...
DeFi(Decentralized Finance),即去中心化金融,是2019年区块链应用发展 最迅猛的一个领域。在以太坊区块链上那些最成功的DApp,例如MakerDAO/DAI、Compound、0x 以及下面我们要介绍的那些,其目标都是颠覆传统的金融服务系统,促进一个全新的数字 经济时代的到来,让每个人都可以获得极大的经济自由度。本文将介绍DeFi的作用、 优势、演化历史、dApp架构等有关DeFi的重要概念,可以帮助你快速了解2019年区块链 的热门概念:DeFi。
用户1408045
2019/05/22
1.5K0
不畏流言,专注于用心打磨技术——OneLedger
熊势之下,哀鸿遍野,看看各个官方群、电报群,看空者多,币圈完全是股市的放大版,人心更浮躁,期望更高摔的更重,毕竟很多人的期望是百倍、是千倍、甚至更高。立秋已过,希望接下去飒爽的秋风多带走人心的不安吧,每天看群也是好玩至甚,今天要为大家介绍的项目OneLedger也难免如此,不过作为技术人员,我们还是看看技术面吧,技术群里无所谓涨跌,只关心项目进度与创新,算是一股清流吧。
区块链领域
2018/08/16
4130
不畏流言,专注于用心打磨技术——OneLedger
开发必读! 手把手教你如何用SPOS解决EOS随机数漏洞
经过2018一整年的发展,区块链的应用落地普遍增加,在公链领域中备受瞩目的链上应用DAPP开发也随着EOS主网的开源而白热化。
区块链大本营
2019/04/28
5580
2021可信区块链评测观察:Chain33底层获市场认可,应用率显著提升
本次大会由中国信息通信研究院、中国通信标准化协会和中国互联网协会指导,可信区块链推进计划、中国互联网协会区块链技术应用工作委员会、中国通信标准化协会可信区块链标准推进委员会和大数据技术标准推进委员会联合主办。
用户7358413
2021/12/25
1K0
EKT多链技术谈 | 共识算法演义——以太坊只能被以太坊打败吗?
摘要:比特币的诞生给我们带来了一个可以自运转网络的成功范例。通过共识算法、加密、点对点网络以及奖励机制等,可以形成一个自治的社区,可以形成一个通过挖矿机制(POW)来达成一种不通过中心机构来达成的信任,最终实现点对点的价值流通。
风中凌乱的靓仔
2019/03/22
7010
EKT多链技术谈 | 共识算法演义——以太坊只能被以太坊打败吗?
推荐阅读
相关推荐
行业资讯 | 区块链或将真正迎来高速发展期!
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验