1. 程式人生 > >C++ premier Plus書之—C++指標,陣列,指標算術

C++ premier Plus書之—C++指標,陣列,指標算術

首先看一下c++裡的動態建立陣列

int* p_array = new int[10];

new運算子返回第一個元素的地址, 也就是會把陣列的第一個元素的地址賦給指標p_array

當使用完new分配的記憶體時, 應該使用delete來釋放他們:

delete[] p_array;

注意new分配記憶體的時候如果是[], delete的時候也需要加[]

動態建立陣列相比與靜態建立陣列的區別是: 動態建立陣列只有在需要的時候才會去真正申請記憶體空間

 

看一個簡單的例子:

#include "iostream"
using namespace std;

int main() {
	// 通過new來分配的記憶體時動態載入的, 
	double* p_double = new double[3];
	// c++裡可以將指標當做陣列的名稱一樣使用, 來訪問陣列中的元素
	// 這是因為c++裡陣列本身就是用指標來處理的
	p_double[0] = 1.1;
	p_double[1] = 1.2;
	p_double[2] = 1.3;
	
	cout << "p_double[1] = " << p_double[1] << endl;
	// 下面的程式碼展示了指標和陣列名的不同
	// 可以對指標進行加減操作, 相當於將指標向後/向前移動
	// 這行的+1 就相當於指標指向了陣列的第二個元素
	// +1增加的量, 相當於指標指向的型別的位元組數
	p_double = p_double + 1;
	cout << "Now p_double[0] = " << p_double[0] << endl;
	cout << "Now p_double[1] = " << p_double[1] << endl;
	// 之所以要-1後再釋放陣列空間, 是因為new的時候是3
	// 所以釋放的時候也需要釋放完全
	p_double = p_double - 1;
	delete [] p_double;
	return 0;
}

程式的執行結果:

c++允許對指標和整數相加, +1 的結果相當於在原來的基礎上加上指標指向的物件所佔的位元組數

 

再看一個數組和指標相互關係的例子:

#include "iostream"
using namespace std;

int main(){
	double d_arr[] = {100.0, 200.0, 300.0};
	short s_arr[] = {1, 2, 3};
	
	// 兩種將陣列的首地址賦值給指標變數的方式
	// 1.將陣列名賦值給指標變數
	double* p_d_arr = d_arr;
	// 2.將陣列的第一個元素的首地址賦值給指標變數
	short* p_s_arr = &s_arr[0];
	
	cout << "p_d_arr = " << p_d_arr << ", *p_d_arr = " << *p_d_arr << endl;
	// 指標向後移動了8個位元組, 也就是指向了陣列的第二個元素
	p_d_arr = p_d_arr + 1;
	cout << "add 1 to the p_d_arr pointer : " << endl;
	cout << "p_d_arr = " << p_d_arr << ", *p_d_arr = " << *p_d_arr << endl;
	
	cout << "p_s_arr = " << p_s_arr << ", *p_s_arr = " << *p_s_arr << endl;
	p_s_arr = p_s_arr + 1;
	cout << "add 1 to the p_s_arr pointer : " << endl;
	cout << "p_s_arr = " << p_s_arr << ", *p_s_arr = " << *p_s_arr << endl;
	
	cout << "*********************************" << endl;
	cout << "s_arr[0] = " << s_arr[0] << ", s_arr[1] = " << s_arr[1] << endl;
	cout << "*s_arr = " << *s_arr << ", *(s_arr + 1) = " << *(s_arr + 1) << endl;
	
	cout << "size of d_arr = " << sizeof(d_arr) << endl;
	cout << "sizeof(p_d_arr) = " << sizeof(p_d_arr) << endl;
}

執行結果如下:

從程式的執行結果可以看出:

從執行結果可以看出:

  1. 一般情況下c++把陣列名解釋為陣列的第一個元素的地址(10~12行程式碼)
  2. 如果arr是陣列名, 那麼arr[i] 被解釋為*(arr + 1)
  3. p_d_arr = p_d_arr + 1執行情況就是將指標移動到陣列的下一個元素的地址(在這裡是向後移動了8個位元組)
  4. 還可以看出s_arr [1] 等價於*( s_arr + 1), 也就是c++在遇到s_arr[1]的時候會相當於做了*(s_arr + 1)這種操作.
  5. 指標和陣列名的區別就是陣列名是常量, 而指標是可以修改指標的值的(也就是可以對指標進行加減等操作), 另外對陣列名進行sizeof得到的是陣列的長度, 而對指標進行sizeof得到的是指標的長度

再看一個更為詳細的陣列和指標的相互關係的demo:

#include "iostream"
using namespace std;

int main(){
	short s_arr[10] = {1, 2, 3};
	
	// 由於s_arr是陣列名,也就是相當於指標, 指向陣列的首地址
	cout << s_arr << endl;
	// 輸出陣列的第一個元素
	cout << s_arr[0] << endl;
	// s_arr相當於指標, *指標 也就是指標指向的地址裡的元素
	cout << *s_arr << endl;
	// 陣列第一個元素的地址
	cout << &s_arr[0] << endl;
	// 由於s_arr相當於指標所以&s_arr 相當於首元素的地址
	cout << &s_arr << endl;
	
	cout << "************" << endl;
	// 由於s_arr相當於指標, 而又指向的是short型陣列
	// 因此+1相當於向後移動了兩個位元組
	cout << "s_arr + 1 = " << s_arr + 1 << endl;
	// &s_arr指向的是一個20個位元組記憶體塊的地址
	// 因此&s_arr + 1, 相當於加了20個位元組的地址
	cout << "&s_arr + 1 = " << &s_arr + 1 << endl;
	
	cout << "*************" << endl;
	// 和&s_arr類似, 也就是p_short這個指標指向了一個20個位元組記憶體塊的地址
	short (*p_short)[10] = &s_arr;
	// p_short的地址和s_arr一樣
	cout << "p_short = " << p_short << endl;
	// 輸出s_arr地址
	cout << "&s_arr = " << &s_arr << endl;
	// 輸出s_arr首元素的地址
	cout << "&s_arr[0] = " << &s_arr[0] << endl;
	// 輸出s_arr首元素
	cout << "s_arr[0] = " << s_arr[0] << endl;
	// 由於p_short指向的是&s_arr, 因此*p_short 就和 s_arr一樣
	cout << "(*p_short)[0] = " << (*p_short)[0] << endl;
	cout << "p_short + 1" << p_short + 1 << endl;
}

執行的結果為:

注意:陣列名被解釋為陣列的第一個元素的地址, 而對陣列名應用地址運算子(&)的時候, 得到的是整個陣列的地址.

看上面的執行結果, 雖然說s_arr和&s_arr的地址相同, 但是代表的含義不同, s_arr代表的是陣列首元素的地址, 而&s_arr代表的是一個20位元組記憶體塊的地址, 所以&s_arr + 1 實際加的是20個位元組