如何正确使用const(常量),define(宏)

前言

在开发中,也许我们会经常使用到宏定义,或者用const修饰一些数据类型,经常有开发者不知道怎么正确使用,导致项目中乱用宏定义与const修饰符。本篇主要介绍在开发中怎么正确使用constdefine(宏定义)

当我们想定义全局共用的一些数据时,比如通知名字,动画时长等等,我们可以用常量变量

  • 宏: // 注意后面不需要带符号 #define ScottDidLoginSuccess @"登陆成功"
  • 变量: // 注意后面一定要带符号 NSString *scottDidLoginSuccess = @"登陆成功";
  • 常量:
// 四种写法     
static const NSString *scottDidLoginSuccess = @"登陆成功";     
const NSString *scottDidLoginSuccess = @"登陆成功";     
NSString const *scottDidLoginSuccess = @"登陆成功";     
NSString *const scottDidLoginSuccess = @"登陆成功";

那么问题来了,我们到底该如何选择呢? 让我来先将一下我对它们之间的理解吧:

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

常量区分

  • 全局常量:不管你定义在任何文件夹,外部都能访问 const NSString *scottDidLoginSuccess = @"登陆成功";
  • 局部常量:用static修饰后,不能供外界访问 static const NSString *scottDidLoginSuccess = @"登陆成功";

const修饰位置不同,代表什么

    // 1.
    const NSString *scottDidLoginSuccess = @"登陆成功";
    // 2.
    NSString const *scottDidLoginSuccess = @"登陆成功";
    // 3.
    NSString * const scottDidLoginSuccess = @"登陆成功";

咋一看,WTF,这不都张一样嘛,其实不一样,下面解释一下各代表什么

  1. *scottDidLoginSuccess不能被修改,scottDidLoginSuccess能被修改
  2. *scottDidLoginSuccess不能被修改,scottDidLoginSuccess能被修改,也就是和第一种情况是一样的
  3. scottDidLoginSuccess不能被修改,*scottDidLoginSuccess能被修改。

结论:const右边的总不能被修改

所以我们一般定义一个常量又不想被修改,应该这样定义: NSString *const scottDidLoginSuccess = @"登陆成功";

两者之间的区别

  • define在预处理阶段进行替换,const常量在编译阶段使用;
  • define不做类型检查,只进行替换,const常量有数据类型,会执行类型检查;
  • define不能调试,const常量可以调试;
  • define定义的常量在替换后运行过程中,会不断占用内存,而const定义的常量存储在数据段,只有一份拷贝,效率更高;
  • define可以定义函数,const不可以。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏纯洁的微笑

jvm系列(一):java类的加载机制

1、什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个 java.lang.Cl...

4006
来自专栏Java技术栈

volatile关键字解析~高级java必问

昨天我介绍了原子性、可见性、有序性的概念,那么今天就来见识下这些概念的主角-volatile关键字。 volatile基本介绍 volatile可以看成是syn...

2816
来自专栏C/C++基础

Linux命令(11)——col命令

col命令是一个标准输入文本过滤器,它从标准输入读取内容,输出到标准输出。在许多UNIX说明文件里,包含控制字符。当我们运用Shell特殊字符>和>>,把说明文...

1032
来自专栏服务端技术杂谈

Golang笔记

静态编译 编译时一个将源代码翻译成低级语言的过程。编译过程比较慢,在设计Go时,编译速度是主要的设计目标之一。静态类型意味着变量必须指定一个类型,如整形,字符串...

3004
来自专栏眯眯眼猫头鹰的小树杈

猫头鹰的深夜翻译:理解java的classloader

Java ClassLoader是java运行系统中一个至关重要但是经常被忽略的组件。它负责在运行时寻找并加载类文件。创建自定义的ClassLoader可以彻底...

1434
来自专栏攻城狮的动态

iOS面试题梳理(二)

35510
来自专栏数说戏聊

05.记录合并&字段合并&字段匹配1.记录合并2.字段合并3.字段匹配3.1 默认只保留连接上的部分3.2 使用左连接3.3 使用右连接3.4 保留左右表所有数据行

将两个结构相同的数据框合并成一个数据框。 函数concat([dataFrame1, dataFrame2, ...])

862
来自专栏生信宝典

Bash概论 - Linux系列教程补充篇

本篇是我最开始学习Linux命令时看的一篇帖子,最早见于ChinaUnix (这次查找其出处时发现2002年就有这篇)。学习过程中,遇到问题就查一下。这次看到,...

1987
来自专栏专注 Java 基础分享

虚拟机类加载机制

虚拟机把字节码文件从磁盘加载进内存的这个过程,我们可以粗糙的称之为「类加载」,因为「类加载」不仅仅是读取一段字节码文件那么简单,虚拟机还要进行必要的「验证」、「...

4707
来自专栏用户2442861的专栏

shell脚本方便操作记录(持续添加)

http://blog.csdn.net/richerg85/article/details/44001501

2231

扫码关注云+社区

领取腾讯云代金券