C語言指針及佔據內存空間

第1、瞭解內存空間

本文章文字有點多,會有點枯燥,配合圖文一塊兒看能夠緩解枯燥,耐心閱讀哦!!!數組

先了解內存地址,才更好的理解指針!學習

咱們能夠把內存想象爲成一列很長很長的貨運火車,有不少大小相同的車箱,而每一個車箱正好至關於在內存中表示一個字節。這些車箱裝着不一樣的貨物,就像咱們的內存要存着各式各樣的數據。測試

多囉嗦一下

咱們平時在電腦上可以聽音樂、看視頻和文章,其實看到的這些東西就是內存中每一個「車箱」裏面的數據,這些數據最終仍是由二進制0/1演變而成。spa

雖然視頻、文章、音樂等這些信息在咱們眼裏是不一樣的,但對於計算機來講它們在內存中都是以二進制的形式來表示。指針

由於咱們要知道去哪存或取數據,因此內存中每一個字節都有對應的編號,就像火車上的車箱編號同樣。而這個內存中每一個字節的編號就是咱們常說的內存地址,是按一個字節接着一個字節的次序進行編址。以下圖所示:code

凡事多問幾個爲何?

1. 爲何內存地址都有0x開頭?視頻

0x 開頭表明以十六進制來表示的意思。blog

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; }

 結果以下:

第2、理解指針

不要把指針想得太複雜,指針的實質就是內存「地址」,能夠說指針就是地址,其實指針就是保存地址的變量。

拿普通變量跟指針變量作比較:

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

經過畫圖來理解:

多級指針也就是指針的指針的指針.....,以此類推便可。

第3、指針運算問題

指針運算是根據指針的類型不一樣而進行運算的,因類型的不一樣,在加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指針等等知識,還須要學習,後續繼續更新。

以上有不恰當或者講得不對的地方,但願各位留言指正,謝謝!

站在巨人的肩膀上!

相關文章
相關標籤/搜索