C語言再學習19 指標 陣列(四)

2021-09-27 08:08:06 字數 3479 閱讀 6953

1.1 指標陣列和陣列指標的記憶體布局

指標陣列:乙個陣列,陣列元素都是指標,陣列佔多少位元組由陣列本身決定。它是:儲存指標的陣列的簡稱。

陣列指標:乙個指標,它指向乙個陣列。在 32 位系統下,指標永遠佔 4 個位元組,至於它指向的陣列佔多少位元組,我們並不知道。它是:指向陣列的指標的簡稱。

/*指標陣列*/

int*p1[10]

;/*陣列指標*/

int(

*p2)[10

];

解釋:運算子 [ ] 的優先順序高於 * 。對於 p1 ,首先和 [ ] 結合,構成乙個陣列定義,陣列名為 p1 ,int * 修飾的是陣列裡面的內容,即為陣列的每個元素。這是乙個包含 10 個指向 int 型別資料的指標,即指標陣列。

對於 p2 ,() 運算子的優先順序高於 [ ] 。* 號和 p2 構成乙個指標定義,指標變數名為 p2 ,int 修飾的是陣列的內容,即陣列的每個元素。注意,陣列在這裡並沒有名字,是個匿名陣列。p2 是乙個指標,指向乙個包含 10 個 int 型別資料的陣列,即陣列指標。可參考下圖加深理解:

#include

intmain

(void);

int*parr[4]

;/*陣列,儲存4個int型別指標變數*/

int(

*ptr)[4

];/*指標,指向含4個元素的一維陣列*/

/*指標陣列測試*/

for(

int i =

0; i <

4; i++

)printf

("指標陣列測試:%d \r\n"

,*parr[2]

);/*陣列指標測試*/

ptr =

&arr;

/*指標變數賦值*/

printf

("陣列指標測試:%d \r\n",(

*ptr)[2

]);getchar()

;return0;

}

測試結果:

我們可以這樣理解:指標陣列是存放一堆指標變數的,使用的時候需要依次去賦值(單獨給每個指標變數賦值),而陣列指標是乙個指標,只需一次初始化即可。陣列指標在記憶體中只佔乙個指標的儲存空間,指標陣列是多個指標變數,以陣列的形式存放在記憶體中,占有多個指標的儲存空間。

1.2 a 與 &a 的區別

void

test

(void);

char

(*p1)[5

]=&a;char

(*p2)[5

]= a;

printf

("陣列指標測試:%c \r\n",(

*p1)[2

]);printf

("陣列指標測試:%c \r\n",(

*p1+1)

[2])

;printf

("陣列指標測試:%c \r\n",(

*p2)[2

]);printf

("陣列指標測試:%c \r\n",(

*p2 +1)

[2])

;}

對於 char(*p2)[5] = a; 編譯時提示資訊如下:

因為在 c 語言中,賦值號(=)兩邊的資料型別必須是相同的,如果不同,就需要強制轉換,&a 是整個陣列的首位址,與左邊指向整個陣列的指標是匹配的,而 a 僅是陣列元素首個元素的位址,即指向單個字元的指標,與左邊指向整個陣列的指標不匹配,進而編譯器提示警告。但是因為 &a 與 a 的數值是一樣的,只是表示的意義不同,所以程式能夠正確執行。但是最好不要這樣使用,盡量規範化。

結構體:

struct test

*p;

根據記憶體對齊原則,我們知道這個結構體大小為:20 位元組。

假設:p 的值為 0x100000;

則:

/*偏移整個結構體的大小*/

(1)p +

0x01

=0x100000

+sizeof

(test)

*0x01

=0x100014

/*p強制轉換成了無符號長整型,數值一旦被轉換,其型別就變了*/

(2)(

unsigned

long

)p +

0x01

=0x100001

/*p強制轉換為無符號整型指標*/

(3)(

unsigned

int*

)p +

0x01

=0x100000

+sizeof

(int)*

0x01

=0x100004

測試程式:

void

ptest

(void);

/*(&a + 1)偏移陣列a長度:4 *sizeof(int)的長度*/

int*ptr1 =

(int*)

(&a +1)

;/*a + 1為陣列a中的第二個元素(即2)*/

int*ptr2 =

(int*)

((int)a +1)

;printf

("ptr1[-1] ---*ptr2 is %x %x \r\n "

, ptr1[-1

],*ptr2)

;}

測試結果:

ptr1 :將 &a + 1 的值強制轉換成 int * 型別,賦值給 int * 型別的變數 ptr1 ,則 ptr1 是指到下乙個陣列 a 的 int 型別的資料,所以 ptr1[-1] 等價於 *(ptr1 - 1),即 ptr1 從新指的位址往後退了 4 byte。故其值為:0x04。

ptr2 :(int)a + 1的值是元素 a[0] 第二個位元組的位址,然後把這個位址強制轉換成 int * 賦值給 ptr2 ,即 *ptr2 的值是元素 a[0] 的第二個位元組開始連續 4 個 byte 的內容。

記憶體布局如下圖:

具體這 4 個位元組裡面儲存的具體數值是多少,就跟儲存的大小端有關係。如上圖所示:因為輸出的結果為:02 00 00 00,可知是小端;如果是大端,則應該輸出:00 01 00 00。

C語言再學習16 指標 陣列(一)

前言 p 乙個 int 型別的模子在記憶體上得到 4 個位元組的空間,然後把這個 4 個位元組大小的空間命名為 p,同時限定這 4 個位元組的空間裡面只能儲存某個記憶體位址,即使存入其他任何資料,都將被當作位址處理,而且這個記憶體位址開始的連續 4 個位元組上只能儲存某個 int 型別的資料。理解 ...

C語言再學習20 指標 陣列(五)

1.1 二維陣列 除了函式,陣列裡可以存放任何資料。char a 3 4 a 1 2 如下圖 實際上,記憶體是線性的,類似於尺子,最小單位為 byte 比如 記憶體位址 0x0000ff00 是指記憶體零位址開始偏移 0x0000ff00 個 byte。實際上二維陣列記憶體的存放如下圖 註解 1 a...

C語言基礎(四)指標 陣列

2016.7.25 任何型別的一維 二維 三維指標占用空間大小相同4個位元組 32位作業系統 8個位元組 64位 指標與陣列 陣列 表示一段連續的記憶體空間,用來儲存多個相同型別的值。1.陣列名的值是陣列首元素的位址 即陣列名是指向陣列首元素的指標 int array 5 printf array ...