您好,登錄后才能下訂單哦!
原文鏈接:https://www.cnblogs.com/l-hh/p/12288613.html
本文章文字有點多,會有點枯燥,配合圖文一起看可以緩解枯燥,耐心閱讀哦!!!
先了解內存地址,才更好的理解指針!
我們可以把內存想象為成一列很長很長的貨運火車,有很多大小相同的車廂,而每個車廂正好相當于在內存中表示一個字節
。這些車廂裝著不同的貨物,就像我們的內存要存著各式各樣的數據。
我們平時在電腦上能夠聽音樂、看視頻和文章,其實看到的這些東西就是內存中每個“車廂”里面的數據,這些數據最終還是由二進制0/1演變而成。
雖然視頻、文章、音樂等這些信息在我們眼里是不同的,但對于計算機來說它們在內存中都是以二進制的形式來表示。
因為我們要知道去哪存或取數據,所以內存中每個字節都有對應的編號,就像火車上的車廂編號一樣。而這個內存中每個字節的編號就是我們常說的內存地址,是按一個字節接著一個字節的次序進行編址。如下圖所示:
1. 為什么內存地址都有0x開頭?
0x 開頭代表以十六進制來表示的意思。
2. 為什么我們平時看到內存地址是這樣的呢?如圖:
因為內存容量很大,容量大字節數自然也多了,所以需要更多位來編址內存地址。上圖的(0x00 ...)內存地址這里只是便于理解!
3. 為什么我那么菜呢?
哈哈哈......你心里沒點*數嗎?
可以使用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指針等等知識,還需要學習,后續繼續更新。
以上有不恰當或者講得不對的地方,希望各位留言指正,謝謝!
站在巨人的肩膀上!
總結
以上所述是小編給大家介紹的C語言指針及占據內存空間,希望對大家有所幫助!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。