在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 <iostream>
#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;
}
额外测试结果
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只会编译一次,缩短编译时间。
网友评论