C語言 指標和陣列

2021-07-30 10:20:32 字數 3687 閱讀 8670

關於c語言中指標和陣列的爭論就像是一場惡戰。一方面,有些人覺得,所有人都必須承認指標與陣列是不同的。而另一些人則認為陣列被當成指標來處理,因此它們不應該有什麼區別。這種現象讓人迷惑。然而,這兩種說法其實都是正確的。

陣列不是指標,指標也不能說是陣列。在c語言中,指標僅在記憶體中代表乙個位址,而陣列是許多連續的記憶體塊,多個型別相似的元素儲存在其中。

陣列表示法vs指標表示法

陣列被當作指標來處理,具體指的下面兩條:

1. 陣列名變數代表了陣列中第乙個元素的位址。它並不是乙個指標,但卻表現得像乙個不能被修改的常指標一樣。

2. 程式在與陣列互動的時候,用指標表示法代替陣列表示法。

我們來看點**吧。

// 初始化陣列

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

我們宣告了乙個包含5個int的陣列,並將陣列名變數numbers賦給了乙個int指標,ptr1。numbers代表了這個陣列第乙個元素的位址,將其賦給ptr1正是把它當成了指標來使用。接著我們用陣列表示法訪問了第乙個元素的值。

第二個例子中,我們用陣列表示法取了陣列中第乙個元素的位址,之後我們用解引用第乙個元素所在位址的方法訪問了它。

第三個例子中,我們用指標運算將陣列中第乙個元素的位址賦值給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);

它會輸出這樣的結果:

numbers =0x7fff5ea3d230

numbers2 = 0x7fff5ea3d250

ptr1 = 0x7fff5ea3d250

ptr2 = 0x7fff5ea3d250

雖然不能直接改變陣列名變數,我們仍然改變

乙個指向這個陣列的指標。**中,我們建立了兩個陣列,兩個int指標。我們將numbers賦給了ptr1,將numbers2賦給了ptr2。接著我們將ptr2賦給了ptr1,最後輸出結果。可以看到,ptr1和ptr2都指向了numbers2陣列的第乙個元素。

C語言指標陣列和陣列指標

初學者總是分不出指標陣列與陣列指標的區別。其實很好理解 指標陣列 首先它是乙個陣列,陣列的元素都是指標,陣列佔多少個位元組由陣列本身決定。它是 儲存指標的陣列 的簡稱。陣列指標 首先它是乙個指標,它指向乙個陣列。在32 位系統下永遠是佔4 個位元組,至於它指向的陣列佔多少位元組,不知道。它是 指向陣...

C語言指標陣列和陣列指標

初學者總是分不出指標陣列與陣列指標的區別。其實很好理解 指標陣列 首先它是乙個陣列,陣列的元素都是指標,陣列佔多少個位元組由陣列本身決定。它是 儲存指標的陣列 的簡稱。陣列指標 首先它是乙個指標,它指向乙個陣列。在32 位系統下永遠是佔4 個位元組,至於它指向的陣列佔多少位元組,不知道。它是 指向陣...

C語言指標陣列和陣列指標

初學者總是分不出指標陣列與陣列指標的區別。其實很好理解 指標陣列 首先它是乙個陣列,陣列的元素都是指標,陣列佔多少個位元組由陣列本身決定。它是 儲存指標的陣列 的簡稱。陣列指標 首先它是乙個指標,它指向乙個陣列。在32 位系統下永遠是佔4 個位元組,至於它指向的陣列佔多少位元組,不知道。它是 指向陣...