最終學習C/C++,遇到很多疑難雜症。希望用自己的理解和圖形化的方式,把核心的問題表達清楚,即使是小白,也能看明白什麼原理!(不忘初心,晚上加雞腿!)
- pa是指針,指向了數組a
- 數組a有10個元素,都初始化好了
- int類型的數組,每個元素佔用4個字節的大小,內存中每4個字節內存存儲了一個元素,共計40個字節大小,右邊暫時省略了!
- 數組名a的值是首元素的地址a[0]的值,雖然a和a[0]表達的不一樣,但是值都一樣的
1.指針與整數的加減(指針的偏移)
#include <stdio.h>
int main() {
int* pa;
int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
pa = &a; // 將指向指針數組a,其實默認指向a[0]這個元素
printf("%d \n", *pa);
printf("%d \n", *pa + 1); // 打印數組後面一個元素的值(內存中的概念是:從當前指針所指向的內存單元開始,往後拖動4個字節,然後再取4個字節的值,最終算出這個元素的值)
printf("%d \n", *pa + 2); // 同理,往指針後面移動8個字節之後,再取連續4個字節的內存,算出的值
printf("================\n");
pa = &a[2]; // 將指針指向數組的第三個元素,a[2]
printf("%d \n", *pa);
printf("%d \n", *pa + 1); //
printf("%d \n", *pa + 2);
return 0;
};
如上代碼中:pa = &a[2]; 其實就是把指針指向了第三個元素(索引爲2),入下圖所示
1
2
3
================
3
4
5
如上可以說明:
- 指針指向的數組,其實就是把指針指向數組默認的首元素,通過指針的偏移,就可以找到最終每個元素的值了。(也可以通過a[i]這種方式獲取值的大小,但這不是我們將要說明的重點)
- 指針既然可以指向第一個元素,也可以指向其他元素,那該如何獲取前面的值呢?
指針與整數的減法?
int main() {
int* pa;
int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
pa = &a[2];
printf("%d \n", *pa);
printf("%d \n", *pa + 1);
printf("%d \n", *pa + 2);
printf("=================\n");
printf("%d \n", *pa - 1); // 左偏移1個元素
printf("%d \n", *pa - 2); // 左偏移2個元素
return 0;
};
3
4
5
=================
2
1
2.數組地址與整數的相加減(數組地址的偏移)
#include <stdio.h>
int main() {
int* pa;
int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
pa = &a;
printf("%x \n", &a);
printf("%x \n", &a[1]);
printf("%x \n", &a[2]);
printf("%x \n", &a + 1);
return 0;
};
3dfe08 // a[0]地址
3dfe0c // a[1]地址
3dfe10 // a[2]地址
3dfe30 // &a + 1地址
通過結果表明:
- 相鄰元素之間的地址確實相差4個字節,32位系統中,int類型確實佔用4個字節大小
- 3dfe30與3dfe08兩個地址相差是40,也就是說,&a+1向右邊偏移了40個字節,就是整個數組的長度。(如果數組a的長度爲5,那麼將移動20個字節)
根據如上的原理,那麼如下的代碼中,*(p_last - 1),最終能打印什麼呢?
int main() {
int* pa;
int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
pa = &a;
printf("%x \n", &a);
printf("%x \n", &a[1]);
printf("%x \n", &a[2]);
printf("%x \n", &a + 1);
int* p_last = &a + 1;
printf("%d \n", *(p_last - 1));
return 0;
};
50f6b4
50f6b8
50f6bc
50f6dc
10
根據如上2個案例的說明:
- int* p_last = &a + 1,說明指針p_last指向的位置,在緊鄰着數組a(佔用40個字節)的右邊,如上圖所示位置
- *(p_last - 1)指針p_last向左偏移4個字節,然後取值,最終查看到的內容爲10
- 上面 (p_last - 1) 如果更換爲p_last -1 最終會打印亂碼,所以案例一中的原理我猜想也是*(p-1)是最合適的寫法
以上案例中:
- 如果是其他類型的數組,例如char類型數組,則每個字符暫用1個字節,10個字符共計佔用10個字節。
- 如上案例中,左移或右移一個元素,代表內存上移動一個字節,&a+1,也就向右移動了10個字節大小的內存