對於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
對於一些常用的常量,推薦使用單獨一個類來進行管理.