前言
我们在日常开发的时候经常需要定义一些公用的常量,比如消息通知的Key
值、一些控件的宽高值等,我们经常使用#define
宏或const
来定义,有时候对于const
的使用的很混乱,在这里记录下加深印象。之前一直使用宏定义字符串常量,但是苹果不推荐这样使用宏,推荐使用const
定义常量字符串或其他类型常量。
宏与const的区别
-
编译处理: 宏是预编译的,在编译之前在预处理器里进行文本替换的;
const
是在编译阶段使用的。 -
类型检查: 宏没有类型,不做类型检查,仅仅是展开,替换文本;
const
具有类型,在编译时会检查常量类型。 -
内存使用: 宏只是展开操作,不会分配内存,多少位置使用,就展开多次。占用的只是代码段,大量用宏会导致二进制文件变大;使用
const
修饰的全局静态常量共享一块内存,如果代码中多次使用,也不会多次分配内存; -
宏的优点: 使用宏可以定义一些函数方法付,单使用
const
修饰的常量无法定义函数方法; - 宏的缺点: 过多的使用宏定义会增加编译时间;
const的作用
- 在声明定义变量时用来修饰右侧的变量,基本变量或指针变量
- 如果变量被const修饰了,则此变量只能是只读的,无法修改变量值;
注:使用时主要关注const的位置,const只修饰表达式右边内容,被const修饰的内容都是常量,不能被修改,
const的基本使用
- 正常定义变量:
//定义变量
int a = 1;
printf("值:%d 变量地址:%p 变量指向地址:%p\n",a,&a,a);
//值:1 变量地址:0x16dcab62c 变量指向地址:0x1
//对变量值进行修改
a = 20;
printf("值:%d 变量地址:%p 变量指向地址:%p\n",a,&a,a);
//值:20 变量地址:0x16dcab62c 变量指向地址:0x14
//未使用const修饰变量的时候,变量值可以修改
- 第一种:修饰变量
const int b1 = 20;
b1 = 10;
//error:Cannot assign to variable 'b1' with const-qualified type 'const int'
//无法修改变量b1的值
int const b2 = 20;
b2 = 10;
//error:Cannot assign to variable 'b2' with const-qualified type 'const int'
//无法修改变量b2的值
//注:因此以上两种使用const的方式修饰右侧内容的效果是相同的!
- 第二种:修饰指针变量
//定义指向int型的指针变量,指向a的地址
int *p = &a;
printf("p值:%d 指针变量地址:%p 指针变量指向地址:%p \n",*p,&p,p);
//p值:20 指针变量地址:0x16f40f618 指针变量指向地址:0x16f40f62c
//*p为取值,取得p的值;&p为指针p的地址;%p = p为指针p指向的地址
//p指向的地址与变量a的地址相同!
int c = 10;
printf("c值:%d c的地址:%p \n",c,&c);
//c值:10 c的地址:0x16b4a7614
//允许修改p指向的地址,指向变量c的地址
p = &c;
printf("p值:%d 指针变量地址:%p 指针变量指向地址:%p c值:%d\n",*p,&p,p,c);
//p值:10 指针变量地址:0x16b8f3618 指针变量指向地址:0x16b8f3614 c值:10
//允许修改p指向的内存中的值
*p = 20;
//此时变量c的值也会改变,打印c的值为20
printf("p值:%d 指针变量地址:%p 指针变量指向地址:%p c值:%d\n",*p,&p,p,c);
//p值:20 指针变量地址:0x16ce93618 指针变量指向地址:0x16ce93614 c值:20
*p是常量,p变量代码
//使用const修饰指针变量,修饰*p
int d = 30;
int e = 50;
int f = 55;
/*const在类型前面*/
const int *p1 = &d;
//此时:*p1是常量,不可修改;p1是变量,可修改;
printf("p1值:%d 指针变量地址:%p 指针变量指向地址:%p \n",*p1,&p1,p1);
//p1值:30 指针变量地址:0x16b0cb600 指针变量指向地址:0x16b0cb610
*p1 = 60;
// error: Read-only variable is not assignable
p1 = &f;
//p1为变量可以修改
printf("p1值Fix:%d 指针变量地址:%p 指针变量指向地址:%p \n",*p1,&p1,p1);
//p1值Fix:55 指针变量地址:0x16b0cb600 指针变量指向地址:0x16b0cb608
/*const在类型后面*/
int const *p2 = &d;
//此时:*p2是常量,不可修改;p2是变量,可修改;
printf("p2值:%d 指针变量地址:%p 指针变量指向地址:%p \n",*p2,&p2,p2);
//p2值:30 指针变量地址:0x16ddcb5f8 指针变量指向地址:0x16ddcb610
*p2 = 60;
// error: Read-only variable is not assignable
p2 = &e;
//p2为变量可以修改
printf("p2值Fix:%d 指针变量地址:%p 指针变量指向地址:%p \n",*p2,&p2,p2);
//p2值Fix:50 指针变量地址:0x16ddcb5f8 指针变量指向地址:0x16ddcb60c
//注:以上两种使用const的方式(在类型前或类型后)修饰右侧内容的效果是相同的!
*p是变量,p常量代码
//const修饰指针变量p
int * const p3 = &d;
//此时:*p3为变量,可修改;p3为常量,不可修改;
printf("p3值:%d 指针变量地址:%p 指针变量指向地址:%p d值:%d\n",*p3,&p3,p3,d);
//p3值:30 指针变量地址:0x16d5fb5f0 指针变量指向地址:0x16d5fb610 d值:30
*p3 = e;
printf("p3值Fix:%d 指针变量地址%p 指针变量指向地址:%p d值:%d\n",*p3,&p3,p3,d);
//p3值Fix:50 指针变量地址0x16d5fb5f0 指针变量指向地址:0x16d5fb610 d值:50d值:50
p3 = &f;
//error: Cannot assign to variable 'p3' with const-qualified type 'int *const'
如何让*p和p都是常量不可修改呢?
这样
//如何让*p和p都是常量不可修改呢?
const int * const p4 = &d;//*p4为常量;p4为变量;
或
int const * const p5 = &d;//*p4为常量;p4为变量;
const与static使用
声明一个只读的静态变量,常用于声明定义常量字符串等。
- static修饰全局变量,改变作用域;修饰局部变量,改变变量生命周期;
- static改变作用域防止重复声明;
- const将不希望被随意改变的变量,变为只读,不可修改;
// 声明一个静态的全局只读常量
static const int a = 20;
// 开发中经常拿到key修改值,因此用const修饰key,表示key只读,不允许修改。
static NSString * const key = @"name";
const与extern使用
开发中经常遇到多个文件使用同一个字符串常量,我们可以使用const与extern组合声明定义字符串常量,一般将这类的字符串常量放入一个公用的全局文件中统一管理,只需要定义一份全局变量,多个文件共享。
#import <Foundation/Foundation.h>
extern NSString *const key;
@interface Unitilty : NSObject
@end
#import "Unitilty.h"
NSString *cone key = @"name";
@implementation Unitilty
@end
网友评论