C語言學習筆記 陣列指標域指標陣列

2021-06-19 09:47:40 字數 3053 閱讀 8210

一、指標陣列和陣列指標的記憶體布局

初學者總是分不出指標陣列與陣列指標的區別。其實很好理解:

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

陣列指標:首先它是乙個指標,它指向乙個陣列。在32 

位系統下永遠是佔

4 個位元組,至於它指向的陣列佔多少位元組,不知道。它是「指向陣列的指標」的簡稱。

下面到底哪個是陣列指標,哪個是指標陣列呢:

a)int *p1[10];

b)int (*p2)[10];

每次上課問這個問題,總有弄不清楚的。這裡需要明白乙個符號之間的優先順序問題。

「」的優先順序比「

*」要高。

p1 先與「

」結合,構成乙個陣列的定義,陣列名為p1,

int *

修飾的是陣列的內容,即陣列的每個元素。那現在我們清楚,這是乙個陣列,其包含

10 個指向

int 

型別資料的指標,即指標陣列。至於

p2 就更好理解了,在這裡「()」的優先順序比「

」高,「

*」號和

p2 構成乙個指標的定義,指標變數名為p2,

int 

修飾的是陣列的內容,即陣列的每個元素。陣列在這裡並沒有名字,是個匿名陣列。那現在我們清楚

p2 是乙個指標,它指向乙個包含

10 個

int 

型別資料的陣列,即陣列指標。

我們可以借助下面的圖加深理解: 二

、位址的強制轉換

先看下面這個例子:

struct test

*p;假設p 

的值為0x100000

。如下表表示式的值分別為多少?

p + 0x1 = 0x___ ?

(unsigned long)p + 0x1 = 0x___?

(unsigned int*)p + 0x1 = 0x___?

我相信會有很多人一開始沒看明白這個問題是什麼意思。其實我們再仔細看看,這個知識點似曾相識。乙個指標變數與乙個整數相加減,到底該怎麼解析呢?

還記得前面我們的表示式「a+1

」與「&a+1

」之間的區別嗎?其實這裡也一樣。指標變數與乙個整數相加減並不是用指標變數裡的位址直接加減這個整數。這個整數的單位不是

byte 

而是元素的個數。所以:

p + 0x1 的值為

0x100000+sizof

(test

)*0x1

。至於此結構體的大小為20byte

,前面的章節已經詳細講解過。所以

p +0x1 

的值為:

0x100014

。(unsigned long)p + 0x1 的值呢?這裡涉及到強制轉換,將指標變數

p 儲存的值強制轉換成無符號的長整型數。任何數值一旦被強制轉換,其型別就改變了。所以這個表示式其實就是乙個無符號的長整型數加上另乙個整數。所以其值為:

0x100001

。(unsigned int*)p + 0x1 的值呢?這裡的

p 被強制轉換成乙個指向無符號整型的指標。所以其值為:

0x100000+sizof

(unsigned int

)*0x1

,等於0x100004

。上面這個問題似乎還沒啥技術含量,下面就來個有技術含量的:在x86 

系統下,其值為多少?

intmain()

;int *ptr1=(int *)(&a+1);

int *ptr2=(int *)((int)a+1);

printf("%x,%x",ptr1[-1],*ptr2);

return 0;

}這是我講課時乙個學生問我的題,他在網上看到的,據說難倒了n 

個人。我看題之後告訴他,這些人肯定不懂彙編,乙個懂彙編的人,這種題實在是小

case

。下面就來分析分析這個問題:

根據上面的講解,&a+1 

與a+1 

的區別已經清楚。

ptr1:將

&a+1 

的值強制轉換成

int*

型別,賦值給

int* 

型別的變數

ptr,

ptr1 

肯定指到陣列

a 的下乙個

int 

型別資料了。

ptr1[-1]

被解析成

*(ptr1-1)

,即ptr1 

往後退4 

個byte

。所以其值為

0x4。

ptr2:按照上面的講解,

(int)a+1 

的值是元素

a[0]

的第二個位元組的位址。然後把這個位址強制轉換成

int*

型別的值賦給

ptr2

,也就是說

*ptr2 

的值應該為元素

a[0]

的第二個位元組開始的連續4 個

byte 

的內容。

其記憶體布局如下圖:

好,問題就來了,這連續4 

個byte 

裡到底存了什麼東西呢?也就是說元素

a[0],a[1]

裡面的值到底怎麼儲存的。這就涉及到系統的大小端模式了,如果懂彙編的話,這根本就不是問題。既然不知道當前系統是什麼模式,那就得想辦法測試。大小端模式與測試的方法在第一章講解

union 

關鍵字時已經詳細討論過了,請翻到彼處參看,這裡就不再詳述。我們可以用下面這個函式來測試當前系統的模式。

int checksystem( )

c;c.i = 1;

return (c.ch ==1);

}如果當前系統為大端模式這個函式返回0

;如果為小端模式,函式返回

1。也就是說如果此函式的返回值為

1 的話,

*ptr2 

的值為0x2000000

。如果此函式的返回值為

0 的話,

*ptr2 

的值為0x100

C語言學習筆記 指標 指標陣列與陣列指標

指標陣列 是乙個陣列,陣列元素為指標 陣列指標 是乙個指標,指向陣列的指標 例如 int p1 5 int p2 5 對於語句int p1 5 因為 的優先順序要比 要高,所以 p1 先與 結合,構成乙個陣列的定義,陣列名為 p1,而 int 修飾的是陣列的內容,即陣列的每個元素。也就是說,該陣列包...

C語言學習筆記 陣列 指標和結構 1

1 使用聯合節省記憶體資源 a 不使用聯合 struct empdates last day 儲存結構如下表示 int days works int month int day int year b 使用聯合 union empdates last day 使用聯合之後的儲存結構 int month...

C語言學習筆記 陣列引數和指標引數

1 c 語言中只會以值拷貝的方式傳遞引數,當向函式傳遞陣列時,將整個陣列拷貝乙份傳入函式導致執行效率低下,c 語言以高效作是最初的設計目標,所以這種方法是不可取的。2 引數位於棧上,太大的陣列拷貝將導致棧溢位。3 將陣列名看做常量指標,傳遞的是陣列的首元素位址,而不是整個陣列。1 二維陣列引數同樣存...