第一、了解記憶體空間
本文章文字有點多,會有點枯燥,配合圖文一起看可以緩解枯燥,耐心閱讀哦!!!
先了解記憶體地址,才更好的理解指標!
我們可以把記憶體想象為成一列很長很長的貨運火車,有很多大小相同的車廂,而每個車廂正好相當于在記憶體中表示一個位元組,這些車廂裝著不同的貨物,就像我們的記憶體要存著各式各樣的資料,


多啰嗦一下
我們平時在電腦上能夠聽音樂、看視頻和文章,其實看到的這些東西就是記憶體中每個“車廂”里面的資料,這些資料最侄訓是由二進制0/1演變而成,
雖然視頻、文章、音樂等這些資訊在我們眼里是不同的,但對于計算機來說它們在記憶體中都是以二進制的形式來表示,
因為我們要知道去哪存或取資料,所以記憶體中每個位元組都有對應的編號,就像火車上的車廂編號一樣,而這個記憶體中每個位元組的編號就是我們常說的記憶體地址,是按一個位元組接著一個位元組的次序進行編址,如下圖所示:

凡事多問幾個為什么?
1. 為什么記憶體地址都有0x開頭?
0x 開頭代表以十六進制來表示的意思,
2. 為什么我們平時看到記憶體地址是這樣的呢?如圖:

因為記憶體容量很大,容量大位元組數自然也多了,所以需要更多位來編址記憶體地址,上圖的(0x00 ...)記憶體地址這里只是便于理解!
3. 為什么我那么菜呢?
哈哈哈......你心里沒點*數嗎?
關于記憶體位元組
- 1個記憶體地址只存1個位元組 (Byte);
- 1個位元組等于8位二進制,每一位二進制的0或1,叫“位元”(bit);
- 位元是最小單位,位元組是位元的集合,也是一個單位;
記憶體給資料型別地址分配如下:
- char:占一個位元組分配一個地址;
- int: 占四個位元組分配四個地址;
- 還有long、float、double等型別,等著你來動手測驗,
可以使用sizeof進行驗證:
#include<stdio.h>
int main () {
printf("sizeof(char)=%u\n",sizeof(char));
printf("sizeof(int)=%u\n",sizeof(int));
return 0;
}
結果如下:

第二、理解指標
不要把指標想得太復雜,指標的實質就是記憶體“地址”,可以說指標就是地址,其實指標就是保存地址的變數,
拿普通變數跟指標變數做比較:
char a; // 定義一個變數a,用于保存char型別的資料;
char *b; // 定義一個指標變數b,用于保存一個記憶體地址,這個記憶體地址上的資料必須是char型別的,
舉個例子,給指標變數進行賦值:
#include<stdio.h>
int main () {
char a = 5; // char 型別占一個位元組;
char *b = &a; // “&”是取變數的地址,取出a在記憶體中的地址;
// 賦值給b指標,此時b變數存盤的就是a地址,
printf("我是a變數的值:%d\n",*b); // *b表示輸出b里面存盤的地址上的資料;
// 證明b上存盤的是a的地址;
printf("我是a的地址:%p\n",&a);
printf("我是b變數的值:%p\n",b);
return 0;
}
輸出結果為:
我是a變數的值:5
我是a的地址:000000000062FE17
我是b變數的值:000000000062FE17
通過畫圖來理解:

通過指標間接性修改變數的值
char a = 5;
char *b = &a;
printf("初始值:a=%d,*b=%d\n",a,*b);
*b = 12; // 其實操作的就是變數a本身的值;
printf("修改后:a=%d,*b=%d\n",a,*b);
------------------------------------------
輸出結果為:
初始值:a=5,*b=5
修改后:a=12,*b=12
指標型別的概念
我們知道char型別的資料只占一個位元組,有很多型別是需要多個位元組來存盤的,像int型別的資料就需要四個位元組來存盤(根據平臺不同,長度也有可能不一致),
對于int型別的指標從當前位元組(地址)開始共四個位元組(地址)都是屬于該變數的值, 而對于char型別則只表示當前位元組(地址),代碼如下:
int a = 259;
int * p1 = &a;
char * p2 = (char *)&a; // 這里需要強制轉換一下型別
printf("*p1=%d,*p2=%d\n",*p1,*p2);
-----------------------
輸出:*p1=259,*p2=3
通過畫圖來便于理解:

通過上文我們已經對int型別指標有所了解了,*p1的輸出是在我們預算范圍之內的,但是為什么*p2輸出的值是3呢?
重點,敲黑板!!!
因為計算機是使用二進制來表示數字的,上面(259)十進制轉換二進制是 [100000011],由于一個int型別變數占用四個位元組,8位二進制為一個位元組,補齊高位的0后,則 [00000000 00000000 00000001 00000011],每8位二進制(一個位元組)換算為十進制,則 [0 0 1 3],
此時你應該差不多明白*p2為什么輸出的值為3了吧,但是記憶體地址中有個概念叫"大小端模式",就會有兩種不同的排序:[0 0 1 3] or [3 1 0 0],
由于計算機讀取*p2的地址是0x00,所以直接輸出這個地址上的資料,你也可以試著改一下,把259換成258/257等,看看是否正如所說,
驗證它們存盤地址,代碼如下:
int a = 259;
int * p1 = &a;
char * p2 = (char *)&a;
printf("*p1=%d,*p2=%d\n",*p1,*p2);
printf("&a=0x%p\n",&a);
printf("p1=0x%p\n",p1);
printf("p2=0x%p\n",p2);
輸出結果正如我們預想的:

當你看到這里的時候,你只是剛剛認識指標而已,以上是我們俗稱的一級指標,一級指標是比較簡單的,還有二級指標和多級指標,更繞、更難理解,接下來介紹一下二級指標,
在講二級指標前,我們是否有疑問:什么是一級指標?什么是二級指標呢?兩者有什么區別呢?
- 一級指標存盤變數的地址,通過這個地址"直接獲取"變數的資料,
- 二級指標存盤一級指標的地址,二級指標通過一級指標"間接獲取"獲取變數的資料,
- 多級指標以此類推,個人理解,講的不對歡迎指正,
再堅持一下,精彩在"下面"!!![/滑稽]
二級指標
“指標的指標”也就是我們俗稱的二級指標,
什么是“指標的指標”,例如下面代碼:
char a = 5;
char * p1 = &a;
char ** p2= &p1;
printf("*p=%d,**p2=%d\n",*p1,**p2); // 輸出:*p1=5,**p2=5
通過畫圖來理解:

多級指標也就是指標的指標的指標.....,以此類推即可,
第三、指標運算問題
指標運算是根據指標的型別不同而進行運算的,因型別的不同,在加1/減1操作時,記憶體分配的空間也不同,
又拿int型別和char型別來作比較,代碼如下:
char型別+1:從輸出結果可以看出地址是遞增1的,正符合char型別占一個位元組的說法,
char c = 'h';
char *a = &c;
for (int i=0;i<3;i++){
printf("a+1=0x%p\n",a + i);
}
--------------------------------
輸出結果:
a+1=0x000000000062FE0F
a+1=0x000000000062FE10
a+1=0x000000000062FE11
int型別+1:輸出的地址之間相差為4,正是int型別占據空間,
int c = 259;
int *a = &c;
for (int i=0;i<3;i++){
printf("a+1=0x%p\n",a + i);
}
--------------------------------
輸出結果:
a+1=0x000000000062FE0C
a+1=0x000000000062FE10
a+1=0x000000000062FE14
char型別和int型別分別+1在記憶體中地址分配,如圖:

指標就介紹到這里,這只是指標的基礎,還有陣列指標、指標陣列、null指標、void指標等等知識,還需要學習,后續繼續更新,
以上有不恰當或者講得不對的地方,希望各位留言指正,謝謝!
站在巨人的肩膀上!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/51125.html
標籤:C
上一篇:C語言for回圈嵌套示例
下一篇:猴博士4小時講完C語言視頻教程
