570 likes | 855 Vues
第 8 章 記憶體指標. 8.0 變數、數值、位址. 8.1 指標與變數. 對 C++ 語言而言, 指標 ( pointers ) 是存放變數或陣列的 位址 ,因此也可以藉由指標 間接 取得變數或陣列中的 值 。 在 多個函數 的程式中,使用時以變數或陣列 指標 作為函數間傳遞的 參數 ,比直接傳送變數或陣列方便且快得多。. 8.1.1 宣告指標變數. 指標變數 (pointer variable) 一般簡稱 指標 (pointer) ,它的用途是存放 記憶體的位址 。
E N D
8.1 指標與變數 • 對C++ 語言而言,指標(pointers)是存放變數或陣列的位址,因此也可以藉由指標間接取得變數或陣列中的值。 • 在多個函數的程式中,使用時以變數或陣列指標作為函數間傳遞的參數,比直接傳送變數或陣列方便且快得多。
8.1.1 宣告指標變數 • 指標變數(pointer variable)一般簡稱指標(pointer),它的用途是存放記憶體的位址。 • 指標變數是C++提供的特殊變數,用於存取或傳遞記憶體位址,就好像int是用於存取或傳遞整數資料等。 • 宣告指標變數和宣告一般變數的方法類似,只是在指標變數前面加上星號(*)或是在資料型態後面加上星號(*)。 資料型態 *指標變數; 資料型態* 指標變數;
8.1.1 宣告指標變數 • 範例 int *numPtr, number; //宣告指標變數與整數變數 int* num1Ptr, num2Ptr; //宣告同列變數為指標變數 int number = 10; //宣告變數number int *numPtr; //宣告指標numPtr
8.1.2 位址運算符號 & &變數名稱 • 範例 int number = 10; //指定number = 10 cout << &number; //輸出number的位址
8.1.3 起始指標位址 • 範例 int number; //宣告變數number int *numPtr; //宣告指標numPtr numPtr = &number; //啟始指標numPtr 資料型態 *指標名稱; 指標名稱 = &變數;
8.1.3 起始指標位址 (續) 資料型態 *指標名稱 = &變數位址; int number; //宣告變數number int *numPtr = &number; //宣告並啟始指標numPtr
8.1.4 間接運算符號 * *指標名稱 • 範例 int x; int number = 10; //number=10 int *numPtr = &number; //numPtr=number的位址 x = *numPtr; //間接取得資料
8.1.4 間接運算符號 * (續) • 範例 int *pointer; //宣告指標 *pointer = 100; //100存入指標位址
//檔案名稱:d:\C++08\C0803.cpp #include <iostream.h> void main(void) { bool boolVar = true; //宣告與起始布林值變數 int intVar = 65536; //宣告與起始整數變數 float floatVar = 123.45f; //宣告與起始單精度變數 double doubleVar = 98765.43; //宣告與起始倍精度變數 bool* boolPtr = &boolVar; //設定boolVar指標 int* intPtr = &intVar; //設定intVar指標 float* floatPtr = &floatVar; //設定floatVar指標 double* doublePtr = &doubleVar; //設定doubleVar指標 cout << "變數名稱 \t變數位址\t變數指標\n"; //輸出表頭 cout << "---------\t--------\t--------\n"; //輸出分隔線 //輸出變數名稱、位址、與指標 cout << "bool \t" << &boolVar << '\t' << boolPtr << endl; cout << "intVar \t" << &intVar << '\t' << intPtr << endl; cout << "floatVar \t" << &floatVar << '\t' << floatPtr << endl; cout << "doubleVar\t" << &doubleVar << '\t' << doublePtr << endl; }
8.1.5 長度運算符號 • sizeof長度運算符號是用來取得變數或指標所佔的記憶體長度(以byte為單位) • 可以取得陣列中的元素個數 sizeof 變數名稱 sizeof array / sizeof array[0]
8.1.5 長度運算符號 • 範例 cout << sizeof(bool); //輸出bool型態的長度1 cout << sizeof(int); //輸出int型態的長度4 cout << sizeof(float); //輸出float型態的長度4 cout << sizeof(double); //輸出double型態的長度8 char *array[] = {"床前明月光,", "疑似地上霜;", "舉頭望明月,", "低頭思故鄉。" }; //宣告陣列指標 int count = (sizeof array)/(sizeof array[0]); //計算元素個數
8.2 指標與陣列 • 指標與變數的關係還算單純,但指標與陣列的關係就複雜多了。 • 陣列名稱本身就是指標,所以可以直接將陣列名稱當作指標來使用外,還可將陣列名稱指定給另外的指標。 • 字串陣列又與一般數值陣列不盡相同,所以字串陣列指標的用法又有些許差異。
8.2.1 陣列指標 資料型態 *指標名稱;指標名稱 = 陣列名稱; int array[10]; //宣告陣列array int *arrayPtr; //宣告指標arrayPtr arrayPtr = array; //啟始指標arrayPtr int array[10]; //宣告陣列array int *arrayPtr = array; //宣告並啟始指標arrayPtr 資料型態 *指標名稱 = 陣列名稱;
8.2.2 陣列元素指標 資料型態 *指標名稱 = &陣列名稱[註標]; • 範例 short array[ ] = {30, 47, 26, 17, 22, 23}; short *arrayPtr; //宣告陣列指標 arrayPtr = &array[0]; //起始陣列指標 cout << "array 的第0個元素是:" << *arrayPtr; arrayPtr = &array[1]; //更新陣列指標 cout << "array 的第1個元素是:" << *arrayPtr; arrayPtr = &array[2]; //更新陣列指標 cout << "array 的第2個元素是:" << *arrayPtr;
//檔案名稱:d:\C++08\C0806.cpp #include <iostream.h> void main(void) { short array[] = {30, 47, 26, 17, 22, 23}; //宣告字串變數 short *arrayPtr; //宣告浮點數指標 const int SIZE = (sizeof array)/(sizeof array[0]); //計算陣列個數 for(int i=0; i<SIZE; i++) { arrayPtr = &array[i]; //更新指標位置 cout << "array 的第 " << i << " 個元素是:"; cout << *arrayPtr << endl; //輸出指標位置資料 } }
8.2.3 指標運算 • 範例 short array[] = {30, 47, 26, 17, 22, 23}; //宣告字串變數 cout << "array[0]=" << *array; //輸出array[0]=30 cout << "array[1]=" << *(array+1); //輸出array[1]=47 cout << "array[3]=" << *(array+3); //輸出array[3]=17 cout << "array[5]=" << *(array+5); //輸出array[5]=23 *(陣列名稱+n)
8.2.3 指標運算 (續) *指標名稱 + n //等於(*指標名稱)+n *指標名稱 - n //等於(*指標名稱)-n • 範例 short array[] = {30, 47, 26, 17, 22, 23}; cout << "array[0]+1 = " << *array+1; //輸出array[0]+1=30+1=31 cout << "array[1]+3 = " << *(array+1)+3; //輸出array[1]+3=47+3=50 cout << "array[3]-5 = " << *(array+3)-5; //輸出array[3]-5=17-5=12
8.2.4 指標增減 ++指標名稱 | 指標名稱++ --指標名稱 | 指標名稱-- • 範例 short array[] = {30, 47, 26, 17, 22, 23}; //宣告字串變數 short *arrayPtr = &array[0]; //指標=array[0]位址 cout << "array 的第0個元素=" << *arrayPtr; //輸出第0元素=30 cout << "array 的第1個元素=" << *(++arrayPtr); //輸出第1元素=47 cout << "array 的第2個元素=" << *(++arrayPtr); //輸出第2元素=26 cout << "array 的第3個元素=" << *(++arrayPtr); //輸出第3元素=17
8.2.4 指標增減 (續) 指標名稱+=n 指標名稱-=n • 範例 short array[] = {30, 47, 26, 17, 22, 23}; //宣告字串變數 short *arrayPtr = array; //指標=array起始位址 cout << "array 的第0個元素=" << *arrayPtr; //輸出第0元素=30 cout << "array 的第1個元素=" << *(arrayPtr+=1); //輸出第1元素=47 cout << "array 的第4個元素=" << *(arrayPtr+=3); //輸出第3元素=22
8.2.5 字串指標 char* 字串名稱 = "字串資料"; char string[] = "ANSI/ISO C++"; //string為字串變數 char *pstring = "Visual C++"; //pstring為字串指標 cout << string; //顯示字串變數值 cout << pstring; //顯示指標位址到字串結束 cout << string[7]; //顯示字串第7元素值 cout << pstring + 7; //顯示指標第7元素至結束
8.2.5 字串指標 (續) char* 字串名稱[長度] = { "字串0", "字串1", "字串2", . . . }; • 範例 char array[4][20] = { "床前明月光", "疑似地上霜", "舉頭望明月", "低頭思故鄉" }; //宣告二維字串陣列 char *parray [4] = { "床前明月光", "疑似地上霜", "舉頭望明月", "低頭思故鄉" }; //宣告一維字串指標
8.2.5 字串指標 (續) • 範例續 cout << array[2] //顯示(2,0)字串 << parray[2] //顯示(2,0)指標 << array[1][4] << array[1][5] //顯示第(1,4)與(1,5)字元 << parray[1]+4; //顯示(1,4)指標至結束
Ex 17 • 寫一C++程式,宣告一個整數變數並設定初值,另宣告一個指標變數,將指標變數的值設為整數變數的位址,請輸出整數變數的值和整數變數的位址,以及指標變數的值和指標變數的位址。
8.3 指標與函數 • 傳遞變數指標 • 傳遞陣列指標 • 傳遞常數指標 • 傳遞字串指標 • 傳回函數指標
8.3.1 傳遞變數指標 • 傳遞變數值(pass-by-value) void main( ) { int var1 = 53, var2 = 75; swap(var1, var2); } void swap(int num1, int num2) { int buffer; buffer = num1; num1 = num2; num2 = buffer; } int num1 = var1 = 53; int num2 = var2 = 75;
8.3.1 傳遞變數指標 (續) • 傳遞變數指標(pass-by-reference) int &num1 = var1; int &num2 = var2;
8.3.1 傳遞變數指標 函數名稱(變數指標); //呼叫敘述 傳回型態 函數名稱(參數型態 *參數名稱) { //函數本體}
8.3.1 傳遞變數指標 (續) • 傳遞變數指標一 int *num1 = &var1; int *num2 = &var2;
8.3.1 傳遞變數指標 (續) • 傳遞變數指標二 int *num1 = pvar1; int *num2 = pvar2;
8.3.2 傳遞陣列指標 函數名稱(陣列指標); //呼叫敘述 傳回型態 函數名稱(參數型態 *參數名稱) { //函數本體} 傳遞陣列指標與傳遞變數指標的函數宣告與函數呼叫 是一樣的,只是呼叫時參數改為陣列名稱。
8.3.2 傳遞陣列指標 (續) • 範例 void main(void) { int source[3] = {5, 9, 3}; showArray(source); //呼叫showArray函數 } void showArray(int *array) //函數,參數為陣列指標 { for (int i=0; i<=2; i++) //輸出迴圈 cout << *(array+i) << endl; //依序輸出source陣列元素 }
8.3.2 傳遞陣列指標 (續) 函數名稱(陣列名稱); //呼叫敘述 傳回型態 函數名稱(參數型態 參數名稱[]) { //函數本體} 與第七章傳遞陣列名稱完全相同
8.3.2 傳遞陣列指標 (續) • 範例 void main(void) { int source[3] = {5, 9, 3}; showArray(source); //呼叫showArray函數 } void showArray(int array[]) //函數,參數為整個陣列 { for (int i=0; i<=2; i++) //輸出迴圈 cout << array[i] << endl; //依序輸出source陣列元素 }
8.3.3 傳遞常數指標 函數名稱(常數指標); //呼叫敘述 傳回型態 函數名稱(const 參數型態 *參數名稱) { //函數本體}
8.3.3 傳遞常數指標 (續) • 範例一 void power(const int *); //計算平方函數原型 void main(void) { const int LEN = 5; //宣告整常數符號 power(&LEN); //傳遞常數指標 } void power(const int *NUM) //計算平方函數 { cout << *NUM * *NUM; }
8.3.3 傳遞常數指標 (續) • 範例二 void power(const int *); //計算平方函數原型 void main(void) { int LEN = 5; //宣告整整數變數 power(&LEN); //傳指呼叫, 傳遞變數位址 } void power(const int *NUM) //接收指標常數 { cout << *NUM * *NUM; }
8.3.4 傳遞字串指標 函數名稱(字串指標); //呼叫敘述 傳回型態 函數名稱(char *參數名稱) { //函數本體}
8.3.4 傳遞字串指標 (續) • 範例 void main(void) { char *str = "You will never win, if you never begin."; toString(str); //傳遞str指標給toString } void toString(char *s) //輸出字串函數 { cout << s << endl; }
//檔案名稱:d:\C++08\C0817.cpp #include <iostream.h> void capital(char *); //宣告函數原型 void main(void) { char str[] = "You will never win, if you never begin.\n"; char *strPtr = &str[0]; //宣告並起始C字串指標 cout << "資料列:" << str; capital(strPtr); //傳遞字串指標給capital cout << "更改後:" << str; } void capital(char *s) //第一個字母改大寫函數 { while(*s != NULL) //若不是字串結尾則繼續 if(*s++ == ' ') { //若*s == ' ' *s -= 32; //則*s++ -= 32 } }
8.3.5 傳回函數指標 *函數名稱(參數); //呼叫敘述 傳回型態 *函數名稱(參數列) //函數表頭{ //函數本體}
8.3.5 傳回函數指標 (續) • 範例 void main(void) { cout << *getNumber(); //取得getNumber()指標值 } float *getNumber() //輸入浮點數函數 { float *num; cin >> *num; return num; }
8.4 動態記憶體 • C++ 語言沒有垃圾回收的功能,所以程式不會自動釋放不再使用的變數或陣列記憶體。因此如果程式配置變數或陣列愈多,則佔據的記憶體就愈多,當然也就影響程式可用的空間,以及影響程式執行的速度。 • 程式設計師如果認為有些變數或陣列可以於用完後立即釋放佔用空間,則可以使用配置動態記憶體的方式來配置動態記憶體變數或陣列。
8.4.1 配置動態記憶體new • 變數指標= new 資料型態(起始資料); • 範例一 int num = 100; int *numPtr = # //*numPtr指向num變數 • 範例二 int *newPtr; //宣告指標變數 newPtr = new int; //配置動態指標變數 *newPtr = 200; //起始指標變數值=200 • 範例三 int *newPtr = new int(200); //*newPtr內值=200
8.4.2 釋放動態記憶體delete • delete 變數指標; • 範例 int *p; //宣告指標 *p = 100; //起始指標的內值 cout << *p << endl; p = new int(200); //配置動態記憶體給指標 cout << *p << endl; delete p; //釋放指標佔用的動態記憶體
8.4.3 配置動態陣列 • 陣列指標 = new 資料型態[長度]; • 範例 int p[10]; //宣告整數陣列p[10]; int i; for(i=0; i<10; i++) p[i] = i; //起始陣列初值 for(i=0; i<10; i++) cout << p[i] << ' '; //輸出陣列元素值