關於c語言中指標和陣列的爭論就像是一場惡戰。一方面,有些人覺得,所有人都必須承認指標與陣列是不同的。而另一些人則認為陣列被當成指標來處理,因此它們不應該有什麼區別。這種現象讓人迷惑。然而,這兩種說法其實都是正確的。
陣列不是指標,指標也不能說是陣列。在c語言中,指標僅在記憶體中代表乙個位址,而陣列是許多連續的記憶體塊,多個型別相似的元素儲存在其中。
陣列表示法vs指標表示法
陣列被當作指標來處理,具體指的下面兩條:
1. 陣列名變數代表了陣列中第乙個元素的位址。它並不是乙個指標,但卻表現得像乙個不能被修改的常指標一樣。
2. 程式在與陣列互動的時候,用指標表示法代替陣列表示法。
我們來看點**吧。
我們宣告了乙個包含5個int的陣列,並將陣列名變數numbers賦給了乙個int指標,ptr1。numbers代表了這個陣列第乙個元素的位址,將其賦給ptr1正是把它當成了指標來使用。接著我們用陣列表示法訪問了第乙個元素的值。// 初始化陣列
int numbers[5] = ;
// 標準陣列表示法
int*ptr1 = numbers;
int val1 = numbers[0];
// 陣列表示法取位址
int*ptr2 = &numbers[0];
int val2 = *(&numbers[0]);
// 指標加偏移表示法
int*ptr3 = numbers + 0;
int val3 = *(numbers + 0);
// 輸出指標中的位址
printf("*ptr1 = %p\n", (void *)ptr1);
printf("*ptr2 = %p\n", (void *)ptr2);
printf("*ptr3 = %p\n", (void *)ptr3);
// 輸出位址指向的int值
printf("val1 = %d\n", val1);
printf("val2 = %d\n", val1);
printf("val3 = %d\n", val1);
第二個例子中,我們用陣列表示法取了陣列中第乙個元素的位址,之後我們用解引用第乙個元素所在位址的方法訪問了它。
第三個例子中,我們用指標運算將陣列中第乙個元素的位址賦值給ptr3,之後我們解引用相同的位址來得到它的值。
最後我們將所有儲存在指標中的位址和所有在這些位址的int值輸出到螢幕上。執行這段**,你會得到類似下面的輸出:
c
所有值都是相同的。接下來再看看下面的**:*ptr1 = 0x7fff6be1de60
*ptr2 = 0x7fff6be1de60
*ptr3 = 0x7fff6be1de60
val1 = 1
val2 = 1
val3 = 1
執行它,你會得到以下輸出:// 初始化陣列
int numbers[5] = ;
int i = 0;
// 用陣列表示法輸出元素
for (i = 0; i < 5; i++ )
// 用指標加偏移輸出元素(真討厭)
for (i = 0; i < 5; i++ )
// 僅用乙個指標輸出元素
int*ptr = numbers;
for (i = 0; i < 5; i++ )
就像你看到的那樣,所有過程得到了相同的結果。numbers[0
]=1numbers[1
]=2numbers[2
]=3numbers[3
]=4numbers[4
]=5*(numbers+0)
=1*(numbers+1)
=2*(numbers+2)
=3*(numbers+3)
=4*(numbers+4)
=50,
*ptr++
=11,
*ptr++
=22,
*ptr++
=33,
*ptr++
=44,
*ptr++
=5
陣列表示法實際上就是指標運算。c語言標準只是將numbers[0]定義為(numbers + 0)的語法糖。(譯者注:語法糖,它意指那些沒有給計算機語言新增新功能,而只是對人類來說更容易理解的語法。)無論何時,你寫下乙個陣列表示法,比方說numbers[2],都會被編譯器轉換為(numbers + 2)。這裡,numbers表示陣列中第乙個元素的位址,+2則表示用於指標運算的偏移量。
陣列變數
我們已經展示了,陣列常被當作指標來處理,而且對於c編譯器而言陣列表示法就是指標運算。一些人自然而然地就做出了這樣的假設:既然陣列能被當成指標,指標也應該能賦值給陣列。這是不對的,陣列名變數不能被改變。我們看看下面的**吧。
c
這段**不能通過編譯。試一試,你會得到以下輸出。// 初始化陣列
int numbers[5] = ;
int numbers2[5] = ;
int *ptr = numbers2;
// 這不能通過編譯
numbers = numbers2;
numbers = &numbers2;
numbers = ptr;
incompatible types when assigning to
type 『int[5]』 from
type 『int *』
incompatible types when assigning to
type 『int[5]』 from
type 『int (*)[5]』
incompatible types when assigning to
type 『int[5]』 from
type 『int *』
它會輸出這樣的結果:// 初始化陣列
int numbers[5] = ;
int numbers2[5] = ;
int *ptr1 = numbers;
int *ptr2 = numbers2;
// 能通過編譯
ptr1 = ptr2;
// 輸出位址
printf("numbers = %p\n", (void *)numbers);
printf("numbers2 = %p\n", (void *)numbers2);
printf("ptr1 = %p\n", (void *)ptr1);
printf("ptr2 = %p\n", (void *)ptr2);
乙個指向這個陣列的指標。**中,我們建立了兩個陣列,兩個int指標。我們將numbers賦給了ptr1,將numbers2賦給了ptr2。接著我們將ptr2賦給了ptr1,最後輸出結果。可以看到,ptr1和ptr2都指向了numbers2陣列的第乙個元素。numbers =0x7fff5ea3d230
numbers2 = 0x7fff5ea3d250
ptr1 = 0x7fff5ea3d250
ptr2 = 0x7fff5ea3d250
雖然不能直接改變陣列名變數,我們仍然改變
C語言指標陣列和陣列指標
初學者總是分不出指標陣列與陣列指標的區別。其實很好理解 指標陣列 首先它是乙個陣列,陣列的元素都是指標,陣列佔多少個位元組由陣列本身決定。它是 儲存指標的陣列 的簡稱。陣列指標 首先它是乙個指標,它指向乙個陣列。在32 位系統下永遠是佔4 個位元組,至於它指向的陣列佔多少位元組,不知道。它是 指向陣...
C語言指標陣列和陣列指標
初學者總是分不出指標陣列與陣列指標的區別。其實很好理解 指標陣列 首先它是乙個陣列,陣列的元素都是指標,陣列佔多少個位元組由陣列本身決定。它是 儲存指標的陣列 的簡稱。陣列指標 首先它是乙個指標,它指向乙個陣列。在32 位系統下永遠是佔4 個位元組,至於它指向的陣列佔多少位元組,不知道。它是 指向陣...
C語言指標陣列和陣列指標
初學者總是分不出指標陣列與陣列指標的區別。其實很好理解 指標陣列 首先它是乙個陣列,陣列的元素都是指標,陣列佔多少個位元組由陣列本身決定。它是 儲存指標的陣列 的簡稱。陣列指標 首先它是乙個指標,它指向乙個陣列。在32 位系統下永遠是佔4 個位元組,至於它指向的陣列佔多少位元組,不知道。它是 指向陣...