ios拓展31-宏(define)和const的正确姿势

在iOS开发中,经常用到宏定义,但是网上看一些博客的时候,有的说宏定义大量使用会重复拷贝,占用内存. 有的说不会.笔者测试了一下

1.代码(define)
#import "ViewController.h"
#define X_NAME @"zha"
#define X_int 1
@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    NSString *st1 = X_NAME;
    NSString *st2 = X_NAME;
    NSLog(@"%p===%p",st1,st2);

    int a1 = X_int;
    int a2 = X_int;
    NSLog(@"%p===%p",&a1,&a2);
}
2.打印结果
结果
3.根据上述结果推测

***- 1宏:只是在预处理器里进行文本替换,没有类型,不做任何类型检查,编译器可以对相同的字符串进行优化。只保存一份到 .rodata 段。甚至有相同后缀的字符串也可以优化,你可以用GCC 编译测试,"Hello world" 与 "world" 两个字符串,只存储前面一个。取的时候只需要给前面和中间的地址,


  • 2 如果是整形、浮点型会有多份拷贝,但这些数写在指令中。占的只是代码段而已,大量用宏会导致二进制文件变大 (笔者并不赞成这个观点,原因如下测试)
4.额外测试(oc和c++结果一样)
#include 
#define X_int 1

int main(int argc, const char * argv[]) {
    std::cout << "Hello, World!\n";
    
    int a1 = X_int;
    int a2 = X_int;
    printf("%p===%p\n",&a1,&a2);
    int const a = 1;
    int aa1 = a;
    int aa2 = a;
    printf("%p===%p",&aa1,&aa2);
    printf("\n==%p",&a);
    
    return 0;
}
ios拓展31-宏(define)和const的正确姿势_第1张图片
额外测试结果
5.内存占用(个人观点,如果有错误,还请指教)

地址的变化,是由于基本数据类型本身造成的. 因此,使用宏定义不会增加内存使用.

6.总结
  • (1) 编译器处理方式不同
    define宏是在预处理阶段展开。
    const常量是编译运行阶段使用。
  • (2) 类型和安全检查不同
    define宏没有类型,不做任何类型检查,仅仅是展开。
    const常量有具体的类型,在编译阶段会执行类型检查。
  • (3) 存储方式不同
    define宏仅仅是展开,有多少地方使用,就展开多少次,不会分配内存。
    const常量会在内存中分配(可以是堆中也可以是栈中)。
  • (4) 提高了效率。 编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。

const 与 #define的比较
C++ 语言可以用const来定义常量,也可以用 #define来定义常量。但是前者比后者有更多的
优点:

  • (1) const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查。而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误(边际效应)。
  • (2) 有些集成化的调试工具可以对const常量进行调试,但是不能对宏常量进行调试。

缺点:

  • (1)宏能定义代码,const不能,多个宏对于编译会相对时间较长,影响开发效率,调试过慢,const只会编译一次,缩短编译时间。

你可能感兴趣的:(ios拓展31-宏(define)和const的正确姿势)