C++中數組和指針的關系(區別)詳解
本文轉自:http://c.biancheng.net/view/1472.html
博主在閱讀后將文中幾個知識點提出來放在前面:
- 沒有方括號和下標的數組名稱實際上代表數組的起始地址,這意味著數組名稱實際上就是一個指針。
- 在數學語句中使用指針時,它不像常規變量那樣工作。
- 向指針添加值時并要解引用時,括號非常重要。
- array[index] 相當于 *(array + index)。
- C++ 不會對數組執行邊界檢查。
- 不僅指針符號可以與數組名稱一起使用,而且下標符號也可以與指針一起使用。
- 可以使用地址運算符來獲取數組中單個元素的地址。
- 數組名稱和指針變量的唯一區別是,不能改變數組名稱指向的地址,即數組名稱可視為一個指針常量。
我們知道,沒有方括號和下標的數組名稱實際上代表數組的起始地址,這意味著數組名稱實際上就是一個指針。下面程序通過顯示與間接運算符一起使用的數組名稱來說明這一點。
// This program shows an array name being dereferenced with the * operator.
#include <iostream>
using namespace std;
int main()
{short numbers[] = {10, 20, 30, 40, 50};cout << "The first element of the array is ";cout << *numbers << endl;return 0;
}
程序輸出結果:
The first element of the array is 10
numbers 在上面程序中的作用類似于指向數組起始地址的指針,所以當 numbers 被解引用時,第一個元素被檢索出來。那么,如何使用間接運算符來檢索數組的全部內容呢?請記住,數組元素是一起存儲在內存中的,如圖 1 所示。
既然 numbers 是 numbers[0] 的地址,那么給 numbers 添加值豈不是就可以獲得數組中其他元素的地址了?這樣想當然很有道理,但是,這里有一個知識點非常重要,即:在數學語句中使用指針時,它不像常規變量那樣工作。
在 C++ 中,當給一個指針添加一個值的時候,實際上添加的值是把這個值乘以指針引用的數據類型的大小。換句話說,如果給 numbers 加 1,實際上就是給 numbers 加上 1 X sizeof(short);如果給 numbers 加 2,實際上就是給 numbers + 2 X sizeof(short),以此類推。在 PC 上,這意味著以下說法是真實的,因為 short(短整數)通常使用 2 個字節:
- *(numbers +1)是指地址 numbers + 1X2 處的值。
- *(numbers + 2)是指地址 numbers + 2X2 處的值。
- *(numbers + 3)是指地址numbers + 3X2 處的值。
以此類推。
這種自動轉換意味著數組中的元素可以通過使用其下標或通過將下標添加到指向數組的指針來檢索。既然表達式 *numbers 與 *(numbers + 0) 相同,它可以檢索數組中的第一個元素,那么*(numbers + 1) 就可以檢索第二個元素。同樣,*(numbers+2) 即可檢索第三個元素,以此類推。圖 2 顯示了下標表示法和指針表示法的等價性。
注意,向指針添加值時,括號非常重要。* 運算符優先于 + 運算符,所以表達式 *numbers + 1 不等于 *(numbers + 1)。表達式 *numbers + 1 的意思是將數組的第一個元素的內容加 1, 而 *(numbers + 1) 則是先給 numbers 加 1,然后對其進行解引用。
下面的程序使用指針符號顯示了被訪問數組的整個內容:
//This program processes an array using pointer notation.
#include <iostream>
using namespace std;
int main()
{const int SIZE = 5; // Size of the arrayint numbers[SIZE]; // Array of integers// Get values to store in the array// Use pointer notation instead of subscriptscout << "Enter " << SIZE << " numbers: ";for (int count = 0; count < SIZE; count++)cin >> *(numbers + count);// Display the values in the array// Use pointer notation instead of subscriptscout << "Here are the numbers you entered:\n";for (int count = 0; count < SIZE; count++)cout << * (numbers + count) << " ";cout << endl;return 0;
}
程序輸出結果:
Enter 5 numbers: 5 10 15 20 25
Here are the numbers you entered:
5 10 15 20 25
在使用數組時,請記住一個規則,即**array[index] 相當于 *(array + index) **。
另外,請注意C++ 不會對數組執行邊界檢查。當使用指針遍歷一個數組時,有可能會給指針一個越出數組邊界的地址。
要理解數組名稱和指針之間的密切關系,請看下面的程序。它定義了一個 double 數組和一個 double 指針,該指針分配了數組的起始地址。隨后,不僅指針符號可以與數組名稱一起使用,而且下標符號也可以與指針一起使用。
// This program uses subscript notation with a pointer
// variable and pointer notation with an array name.
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{const int NUM_COINS = 5;double coins[NUM_COINS] = {0.05, 0.1, 0.25, 0.5, 1.0};double *doublePtr; // Pointer to a double// Assign the address of the coins array to doublePtrdoublePtr = coins;// Display the contents of the coins array// Use subscripts with the pointer!cout << setprecision (2);cout << "Here are the values in the coins array:\n";for (int count = 0; count < NUM_COINS; count++)cout << doublePtr [count] << " ";// Display the contents of the coins array again, but this time use pointer notation with the array name!cout << "\nAnd here they are again:\n";for (int count = 0; count < NUM_COINS; count++)cout << *(coins + count) << " ";cout << endl;return 0;
}
程序輸出結果:
Here are the values in the coins array:
0.05 0.1 0.25 0.5 1
And here they are again:
0.05 0.1 0.25 0.5 1
注意,當一個數組的地址分配給一個指針時,就不需要地址運算符了。由于數組的名稱已經是一個地址,所以使用 & 運算符是不正確的。但是,可以使用地址運算符來獲取數組中單個元素的地址。
例如,&numbers[1] 得到 numbers[1] 的地址。在程序下面程序中就使用了該技巧。
// This program uses the address of each element in the array.
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{const int NUM_COINS = 5;double coins[NUM_COINS] = {0.05, 0.1, 0.25, 0.5, 1.0};double *doublePtr; // Pointer to a double//Use the pointer to display the values in the arraycout << setprecision (2);cout << "Here are the values in the coins array:\n";for (int count = 0; count < NUM_COINS; count++){doublePtr = &coins[count];cout << *doublePtr << " ";}cout << endl;return 0;
}
程序輸出結果:
Here are the values in the coins array:
0.05 0.1 0.25 0.5 1
數組名稱和指針變量的唯一區別是,不能改變數組名稱指向的地址。例如,假定存在以下定義:
double readings[20], totals[20];
double *dptr;
那么以下語句是合法的:
dptr = readings; // 使 dptr 指向 readings
dptr = totals; // 使 dptr 指向 totals
但是以下語句則是非法的:
readings = totals; // 非法!不能改變 readings
totals = dptr; // 非法!不能改變 totals
數組名稱是指針常量。不能讓它們指向除了它們所代表的數組之外的任何東西。