对于const
修饰符来说, 最简单的理解方式为:
const
右边修饰的是什么, 则, 什么不可变.
如:
int const *p = &c;
此时 p
变量的指针不可变, 其指针地址不会变.及指针常量.
int * const d = &b;
此时 const
直接修饰变量d
, 及变量d
一旦初始化后, 其指针所指向的地址是不能被改变的. 但可以通过修改所指向的地址的值来改变变量d的值.
下面通过示例来详细了解一下其定义:
/*
指针常量:即指针本身的值(也就是内存地址)是不可改变的,而指针指向的变量的值是可以改变的;
*/
int a = 10;
int b = 30;
int c = 20;
int const *p = &c;
/*
(lldb) po &p //p指针的地址
0x00007fff5c5cda88
(lldb) po p
0x00007fff5a5a2a94
(lldb) po &c
0x00007fff5a5a2a94
从打印的信息可以看出, p int指针存放的是变量c的地址.
*/
p = &a; //p指向a的地址
//*p = 20; // *p取得是p变量的地址. error Read-only variables is not assignable
/*
(lldb) po &p
0x00007fff5c5cda88 //p指针的地址没有变
(lldb) po &a
0x00007fff5c5cda9c //a变量的地址
(lldb) po p
0x00007fff5c5cda9c //p变量存的地址已经为a的地址 也就是说, p指针的地址此时存放的是a变量的地址
(lldb) po *p //此时取值, 为a的值10
10
所以, 在这种情况下, 变量p存的值还是可以通过直接赋值改变的
*/
/*
常量指针:即指针指向的变量的值是不可改变的,而指针本身的值是可以改变的;
*/
int * const d = &b; //d指向b的地址, b的地址存放的是对应的b的值(30)的地址
/*
(lldb) po d
0x00007fff50d83a98
(lldb) po &d
0x00007fff5e89fa80
(lldb) po &b
0x00007fff50d83a98
(lldb) po *d
30
*/
//d = 20; //error Cannot assign to variable 'd' with const-qualified type int * const
*d = c; //*d的地址的值为c的值.
/*
(lldb) po &d
0x00007fff5e89fa80
(lldb) po *d
20 //此时d的地址中的值已经指向的c
(lldb) po d
0x00007fff50d83a98
(lldb) po b //此时b的值也改变了.(因为将b的地址指向的值改变了)
20
这种情况下, 只能通过改变d变量的指针的值来修改d变量的值, 而不能直接通过赋值更改.
*/
根据上述示例可以看出, 对于在iOS开发中,都是推荐使用常量指针的方式来定义一个不可变值.
在iOS开发中static
修饰的是一个静态的值, 其和const
最明显的差别是可以被改变, 并且不能被外部文件通过extern
修饰符来引用.
static int a = 10;
(lldb) po a
10
//此时改变a的值
a = 20;
(lldb) po a
20
如果想要申明一个可以被外部引用的一个常量值, 则可以这样定义:
我在AppDelegate.m文件中声明了以下变量:
@interface AppDelegate ()
@end
NSString * const constString = @"constString-哈哈哈哈...";
int const abc = 1024;
@implementation AppDelegate
...
在其他想要使用的文件中:
extern NSString * const constString;
extern int abc;
NSLog(@"%@, %d", constString, abc);
此时输出Log
[3275:789442] constString-哈哈哈哈..., 1024
对于一些常用的常量,推荐使用单独一个类来进行管理.