最近在研究oc的底層,全是c/c++的代碼,雖然以前學(xué)過(guò)也寫(xiě)過(guò),其實(shí)不怎么用都忘得差不多了租副。
首先我們來(lái)了解一下 *
和 &
這兩個(gè)符號(hào)
通俗點(diǎn)兒理解其實(shí)
&地址
就是就是一個(gè)存放地址的變量存儲(chǔ)空間,當(dāng)p指針
指向某個(gè)變量尖滚,這時(shí)這個(gè)p指針
里就存放了那個(gè)變量的地址。這就是我們常說(shuō)的指針指向一個(gè)地址谣蠢,意思是通過(guò)它能找到以它為地址的內(nèi)存單元缸浦。利用指針我們可以直接獲取變量中的值用,要是在指針前加*
就是取其真值了(也就是被指向的變量的值)
//寫(xiě)一串代碼
int arr[5] = {1,2,3,4,5};
int * p = &arr[0];
首先初始化了在32位RAM處理器中的arr數(shù)組占20
個(gè)字節(jié)(int 占用4個(gè)字節(jié)渣慕,32比特)嘶炭,然后我們定義了 一個(gè)int 類型的指針變量p
,指針p
指向了&arr[0] 也就是 arr數(shù)組的第一個(gè)元素地址。
聲明中: * 表示指針逊桦,例如: int p眨猎,p是指針,指向整型量强经。p表示指針指向的整型量的值睡陪。
語(yǔ)句中,p表示指針指向的地址匿情。如果p是指針兰迫,沒(méi)有 &p 形式。二炬称、 x指令:
聲明中:a是整型量汁果。&a是整型量a的地址,不是指針玲躯。
語(yǔ)句中:a是整型量a的值据德。&另一用途是按位運(yùn)算符,按位* 是乘號(hào)跷车。
此時(shí)此刻棘利,你是不是對(duì)指針變量和地址有了一定的認(rèn)知了。指針也不過(guò)如此嘛?
在此之前我們先看下下列問(wèn)題
int arr[5] = {1,3,5,7,9};
arr = ?
arr[0] = ?
&arr = ?
&arr[0] = ?
&arr+1 = ?
&(arr + 1) = ?
lldb打印內(nèi)容:
(lldb) po arr[0]
1
(lldb) po arr
(lldb) po &arr
0x00007ffeefbff4c0
(lldb) po &arr[0]
0x00007ffeefbff4c0
(lldb) po &arr + 1
0x00007ffeefbff4d4
(lldb) po &arr[1]
0x00007ffeefbff4c4
(lldb) po (arr + 1)
0x00007ffeefbff4c4
(lldb) po *(arr + 1)
3
先打印了 arr[0]
等于1姓赤。
再打印了 arr
什么也沒(méi)打印出來(lái)
再打印了 &arr
arr數(shù)組的首地址
再打印了 &arr[0]
arr數(shù)組首元素地址
再打印了&arr + 1
未知地址
再打印了&arr[1]
arr數(shù)組第二個(gè)元素的地址
再打印了 arr + 1
arr數(shù)組第二個(gè)元素的地址
在打印了 *(arr + 1)
arr數(shù)組第二個(gè)元素
此時(shí)此刻 其實(shí)我們只有一個(gè)疑問(wèn) arr 到底是什么赡译?
arr
是數(shù)組名稱, &arr
表示數(shù)組首地址不铆,arr
表示數(shù)組首元素地址
這個(gè)結(jié)論是怎么來(lái)的呢蝌焚?
由arr + 1
和 &arr + 1
的結(jié)果不同
說(shuō)明一下
地址 + int
后面的int
所代表的字節(jié)是根據(jù)當(dāng)前地址
類型來(lái)
假如前面的地址所代表的是元素類型地址那么所加的 元素字節(jié)為int * 單個(gè)元素的字節(jié)
假如前面的地址所代表的是數(shù)組類型地址那么所加的 元素字節(jié)為int * 數(shù)組的字節(jié)
然后再根據(jù)元素字節(jié)獲取當(dāng)前地址
arr + 1
是arr數(shù)組第二個(gè)元素的地址裹唆,所以arr表示數(shù)組首元素地址,&arr + 1
未知地址 說(shuō)明此時(shí)的地址已經(jīng)越過(guò)了當(dāng)前數(shù)組內(nèi)的地址
int arr[5] = {1,3,5,7,9};
int * p = (int*)(&arr+1);
printf("%d\n",*(p-2));
打印7
此時(shí)此刻 p
指向&arr + 1
的地址 只洒,也就是超越了數(shù)組界限的下一個(gè)地址许帐。 我們用p-2
往上走了8個(gè)字節(jié),也就到了數(shù)組的倒數(shù)的第二個(gè)元素的地址毕谴。由此看來(lái) &arr
表示數(shù)組首地址成畦。
那么猜想一下
&arr +2
的地址呢?
小試牛刀:
- 1.請(qǐng)寫(xiě)出以下代碼輸出
int a[5] = {1,3,5,7,9};
int *ptr = (int*)(&a+1);
printf("%d, %d", *(a + 1), *(ptr - 1));
解析:
&a : 代指 數(shù)組的整體 的地址涝开,這里的 a是數(shù)組整體
a+1: 代指 數(shù)組的第一個(gè)成員循帐,這里的 a是數(shù)組首地址
- 2.寫(xiě)一個(gè)標(biāo)準(zhǔn)宏Max,并給出以下代碼的輸出
int array[5] = {1, 2, 3, 4, 5};
int *p = &array[0];
int max = Max(*p++, 1);
printf("%d %d", max, *p);
參考答案: 1舀武,2
#define Max(X, Y) ((X) > (Y) ? (X) : (Y))
當(dāng)看到宏時(shí)拄养,就會(huì)想到宏定義所帶來(lái)的副作用。對(duì)于++银舱、–瘪匿,在宏當(dāng)中使用是最容易產(chǎn)生副作用的,因此要慎用寻馏。
分析:
p指針指向了數(shù)組array的首地址棋弥,也就是第一個(gè)元素對(duì)應(yīng)的地址,其值為1.
宏定義時(shí)一定要注意每個(gè)地方要加上圓括號(hào)
*p++相當(dāng)于*p, p++,所以Max(*p++, 1)相當(dāng)于:
(*p++) > (1) ? (*p++) : (1)
=>
(1) > (1) ? (*p++) : (1)
=>
第一個(gè)*p++的結(jié)果是诚欠,p所指向的值變成了2顽染,但是1 > 1為値,所以最終max的值就是1聂薪。而后面的(*p++)也就不會(huì)執(zhí)行家乘,因此p所指向的地址對(duì)應(yīng)的值就是2蝗羊,而不是3.
擴(kuò)展:如果上面的*p++改成*(++p)如何藏澳?
(*++p) > (1) ? (*++p) : (1)
=>
(2) > (1) ? (*++p) : (1)
=>
max = *++p;
=>
*p = 3,max = 3;
3.請(qǐng)寫(xiě)出c語(yǔ)言整型和字符型數(shù)組的所有定義方法耀找,并根據(jù)該文章寫(xiě)出打印出的相對(duì)應(yīng)的地址代表什么
4.鏈表和數(shù)組的區(qū)別
5.單向鏈表和雙向鏈表的區(qū)別
6.請(qǐng)寫(xiě)出以下代碼的輸出
int i[] = {10, 20, 30, 40, 50};
int *pa[] = {i, i+2, i+1, i+4, i+3};
int **p = pa;
printf("Initial **p = %d\n", **p);//10
p++;
printf("After p++, the **p = %d\n", **p);//30
++*p;
printf("After ++*p, the **p = %d\n", **p);//40
**p++;
printf("After **p++, the **p = %d\n", **p);//20
++**p;
printf("After ++**p, the **p = %d\n", **p);//21
Initial **p = 10
After p++, the **p = 30
After ++*p, the **p = 40
After **p++, the **p = 20
After ++**p, the **p = 21
定義分析 : (右結(jié)合性)
int i[] = {10, 20, 30, 40, 50}; //定義一個(gè)一維整型數(shù)組
int *pa[] = {i, i+2, i+1, i+4, i+3};//定義一個(gè)指針數(shù)組pa,pa[0],pa[1]分別執(zhí)行I數(shù)組的某一個(gè)元素的地址
int **p = pa;//定一個(gè)二重指針(指向指針的指針)p 指向的是pa的地址既&pa(既指針數(shù)組pa的首地址的地址),
printf("Initial **p = %d\n", **p);//10
p++;//p++ 運(yùn)行后表示p指向針數(shù)組pa的首地址的下一個(gè)地址
printf("After p++, the **p = %d\n", **p);//30
++*p;//右結(jié)合性 相當(dāng)于++(*p),*p表示指針數(shù)組pa的第二個(gè)元素的值既整型數(shù)組i的第3個(gè)地址,++后*p指向整型數(shù)組i的第4個(gè)地址,p指向指針數(shù)組pa的第二個(gè)元素的地址
printf("After ++*p, the **p = %d\n", **p);//40
**p++;//右結(jié)合性 相當(dāng)于**(p++),此時(shí)p指向指針數(shù)組pa的第二個(gè)元素的地址,++后p指向指針數(shù)組pa的第三個(gè)元素的地址
printf("After **p++, the **p = %d\n", **p);//20
++**p;//右結(jié)合性 相當(dāng)于++(**p),此時(shí)p指向指針數(shù)組pa的第三個(gè)元素的地址,**p則為整型數(shù)組的第二個(gè)元素的值,++后 **p = 21
printf("After ++**p, the **p = %d\n", **p);//21