专栏首页mukekeheart的iOS之旅iOS学习——#define、const、typedef的区别

iOS学习——#define、const、typedef的区别

在iOS开发中经常遇到一些字段和类型的定义,例如配置生产和测试不同环境的参数等,这时候经常用到#define、const以及typedef。那么它们之间有什么区别呢?我们接下来一个一个具体了解下。

一、基本概念

1.1、#define

  #define并不是定义全局变量,而是宏定义。也就是说并不是真正意义上的定义变量,而是用来做文本替换。当程序开始运行时,编译器会先将代码中的MAX全部替换为100,然后再进行编译。由此可得,#define并不是在编译过程中进行,而是在预编译阶段进行。

#define MAX 100 

  宏的常见用法:

  • 常见的字符串抽成宏:比喻定义的常用颜色、字体字号等
#define kWaterAlpha 0.04f  //水印的透明度

#define kFlowRowSize 30  //流程每次拉去的数量

#define ROW_SIZE 20  //一般刷新每次拉去的数量
  • 常见代码抽成宏:比喻单例模板等
//宏定义常用的颜色
#define XRGB(r,g,b)     [UIColor colorWithRed:(0x##r)/255.0 green:(0x##g)/255.0 blue:(0x##b)/255.0 alpha:1]
#define kBgColor XRGB(f4, f4, f4)
#define kBlackFontColor XRGB(33, 33, 33)
#define kGrayFontColor XRGB(99, 99, 99)
#define kBlueFontColor XRGB(3d,9a,e8)

//宏定义获取当前主界面rootViewController
#define RootVC [UIApplication sharedApplication].delegate.window.rootViewController

//宏定义获取当前的界面
#define TopVC ([RootVC isKindOfClass:[UITabBarController class]]?[((UITabBarController *)RootVC).selectedViewController topViewController]:RootVC)

//宏定义单例的定义和实现
#define DECLARE_DEFAULT  +(instancetype)defaultInstance;

#define IMPLEMENT_DEFAULT(C)  +(instancetype)defaultInstance{\
static dispatch_once_t onceToken;\
static C *_gInstance;\
dispatch_once(&onceToken, ^{\
_gInstance = [C new];\
});\
return _gInstance;\
}

  关于#define的其他用法可以参见后面这篇博文:iOS开发中你真的会用#define么!!!?

1.2、const

  关键字const用来定义常量,如果一个常量被const修饰,那么他的值就不能被改变。编译器通常不为普通const常量分配存储空间,而是保存于符号表中,这使得它成为一个编译期间的常量,没有存储与读内存的操作,使得它的效率更高。

  常见用法如下:

//全局变量,constString1地址不能修改,constString1值能修改
const NSString *constString1 = @"I am a const NSString * string";
//意义同上,无区别
NSString const *constString2 = @"I am a NSString const * string";
// stringConst 地址能修改,stringConst值不能修改
NSString * const stringConst = @"I am a NSString * const string";
  • constString1 跟constString2 无区别
  • 左边代表指针本身的类型信息,const表示这个指针指向的这个地址是不可变的
  • 右边代表指针指向变量的可变性,即指针存储的地址指向的内存单元所存储的变量的可变性

1.3、typedef

  typedef常用于给类型起别名(给已知的类型起别名)。常用于简化复杂类型,变量类型意义化等。typedef是类型替换,语句的一种,结尾必须有;。

//iOS底层源码就是对NSInteger进行了一个别名的设置,其表示的就是long或者int类型。
#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
    typedef long NSInteger;
    typedef unsigned long NSUInteger;
#else
    typedef int NSInteger;
    typedef unsigned int NSUInteger;
#endif

  在iOS开发中最常用到的应该就是使用typedef定义枚举和block了,此外还可以用typedef定义函数。关于typedef定义枚举官方API是这样说的

/* NS_ENUM supports the use of one or two arguments. The first argument is always the integer type used for the values of the enum. The second argument is an optional type name for the macro. When specifying a type name, you must precede the macro with 'typedef' like so:
NS_ENUM支持单个或两个参数,第一个参数一般是NSInteger类型来制定枚举的值类型,第二个参数是可选的枚举类型的别名,如果要定义别名,必须使用typedef进行定义,具体格式如下:
 
typedef NS_ENUM(NSInteger, NSComparisonResult) {
    ...
};
 
If you do not specify a type name, do not use 'typedef'. For example:
如果不需要使用特定的名称,则不需要使用typedef
 
NS_ENUM(NSInteger) {
    ...
};
*/

  typedef的常见用法如下:

typedef double NSTimeInterval;  //给double取别名为NSTimeInterval(变量类型意义化)
typedef NSTimeInterval MyTime;  //给NSTimeInterval取别名为MyTime
typedef char * MyString;  //给char *取别名为MyString

//c语言格式,给Person结构体取别名为MyPerson。使用:MyPerson p = {"jack"};
typedef struct Person {
    char *name 
}MyPerson; 

//c语言格式,给Gender枚举取别名为MyGender。使用:MyGender g = Man;
typedef enum Gender {
    Man,
    Woman 
}MyGender; 

//OC语言格式,给Gender枚举取别名为MyGender。使用:MyGender g = Man;
typedef NS_ENUM(NSInteger, Gender) {
    Man,
    Woman
};

//给block取别名MyBlock
typedef void(^MyBlock) (int a,int b); 
 
//给指向函数的指针取别名MyFunction
typedef int(*MyFunction) (int a,int b); 

typedef定义函数的示例:

int add (int a, int b){
     return a + b;
}

typedef int(*MyMethod) (int a,int b);

int main(){
    MyMethod m = add;
    m(5,6);   //调用函数
    return 0;
}

二、区别

2.1 #define与const

  • 宏在预编译时处理(宏在编译开始之前就会被替换);而const会在编译时被处理
  • #define宏没有类型,宏不做任何类型检查,不会报编译错误,只是替换;而const常量有具体的类型,会编译检查,会报编译错误
  • 宏能定义一些函数,方法;const不能
  • 使用大量宏,容易造成编译时间久,每次都需要重新替换
  • 宏仅仅是展开,有多少地方使用,就展开多少次,不会分配内存。(宏定义不分配内存,变量定义分配内存。);而const常量会在内存中分配(可以是堆中也可以是栈中),const 可以节省空间,避免不必要的内存分配

const

#define PI 3.14159 //常量宏

const doulbe Pi=3.14159; //此时并未将Pi放入ROM中

double I=PI; //预编译期间进行宏替换,分配内存

double i=Pi; //此时为Pi分配内存,以后不再分配!

double J=PI; //再进行宏替换,又一次分配内存

double j=Pi; //没有内存分配

  • const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝(因为是全局的只读变量,存在静态区),而 #define定义的常量在内存中有若干个拷贝。
  • 编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。

2.2 typedef和#define

  • define是文本替换,属于预编译指令,本身不参与编译,除非希望替换的文本中有;否则不用加。 typedef是类型替换,语句的一种,结尾必须有;
  • define写在方法/函数中则作用域从写的地方开始有效,直至使用#undef(不写此指令则后面一直有效)。typedef写在方法/函数中则作用域 只在此方法/函数中有效。
  • 若使用 则 MyString s1,s2等价于 char *s1; char *s2; 若使用 #define MyString char * 则 MyString s1,s2等价于 char *s1,s2char *s1; char s2 再次说明了typedef是类型替换,直接参与编译,而define只是简单的文本替换。

typedef char * MyString;

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Flutter中如何实现扫码

    关于barcode_scan这个扫码组件,针对iOS和Android环境,都要进行对应的环境配置。iOS的配置相对简单,Android的配置就比较繁琐了。

    拉维
  • 移动5G新时代,iOS开发者如何涨薪逆生长!

    次年App store正式对外开放,这也意味着属于开发者的移动互联网时代真正开始,iOS开发者应时代而生,成为安卓之后真正的“时代宠儿”!在移动开发飞速发展的催...

    iOSSir
  • 如何构建一套高可用的移动消息推送平台?

    消息推送作为移动 APP 运营中的一项关键技术,已经被越来越广泛的运用。本文追溯了推送技术的发展历史,剖析了其核心原理,并对推送服务的关键技术进行深入剖析,围...

    Java3y
  • Linux 操作系统下为网卡配置ip

    在Linux下网卡接口逻辑名被称为eth0,eth1,eth2,.....,ethN,所有网卡接口的配置文件都存储在/etc/sysconfig/networ...

    授客
  • 手机备忘录删除了怎么恢复?你值得拥有的方法

      手机备忘录删除了怎么恢复?苹果手机上的备忘录删除了怎么恢复?很多小伙伴最近都遇到过这样的问题,记录在手机里面的备忘录突然不见了,又感觉是被自己删除了,可是就...

    科技第六人
  • 常见的 移动端问题

      <meta name="viewport" content="width=device-width,initial-scale=1.0,minimum-sc...

    小蔚
  • Flutter之 State 生命周期

      State 的生命周期,指的是在用户参与的情况下,其关联的 Widget 所经历的,从创建到显示,再到更新最后到停止,直至销毁等各个阶段

    用户6050340
  • 我决定放弃iPhone了,不只是因为钱的问题

    从朋友圈和互联网的舆情来看,今年的苹果秋季发布会,是有史以来最冷淡的一次。表面上看,与毛衣战有一定的关系,深层次看则是因为苹果不思进取。

    罗超频道
  • “如果有一天苹果丧失创新基因,我会离开。”

    王兴曾是C2C(Copy 2 China)的典型创业,先后模仿美国的Facebook、Twitter和Groupon创办校内网、饭否网和美团。今天,美团市值53...

    罗超频道
  • RTMP/RTSP直播播放器的几种选择

    播放网络视频,通常解析库我们可以有多个选择,如FFMPEG,Daniulive SDK 或者 vitamio。

    daniulive

扫码关注云+社区

领取腾讯云代金券