01 /*file name: return_pointer_1.cpp*/ 02 03 #include<iostream> 04 #include<cstdio> 05 using namespace std; 06 char* test() 07 { 08 int i; 09 char a[5] = "A"; 10 char *ptr = a;//ptr 指向的 a 是函式是屬於區域變數,回到主程式後記憶體被釋放 11 cout << "函式內:\n" << "值: "; 12 for(i = 0; i < 5; i++) 13 printf("%d ", *(ptr+i)); 14 cout << endl; 15 cout << "址: "; 16 for(i = 0; i < 5; i++) 17 printf("%p ", (ptr+i)); 18 cout << endl; 19 return ptr; 20 } 21 int main() 22 { 23 char *name; 24 name = test(); 25 int i; 26 cout << "回傳後:\n" << "值: "; 27 for(i = 0; i < 5; i++) 28 printf("%d ", *(name+i)); 29 cout << endl; 30 cout << "址: "; 31 for(i = 0; i < 5; i++) 32 printf("%p ", (name+i)); 33 cout << endl; 34 }
執行結果:
函式內:
值: 65 0 0 0 0
址: 0042F9A4 0042F9A5 0042F9A6 0042F9A7 0042F9A8
回傳後:
值: -1 -1 -1 -1 -26
址: 0042F9A4 0042F9A5 0042F9A6 0042F9A7 0042F9A8
從return_pointer_1.cpp可見,當要回傳的指標ptr指向的是一個函式內的區域變數,回傳後主程式收到的位址沒錯,但因為函式結束,a陣列被釋放掉了,所以主程式無法取得函式中a陣列的值。
如果想要回傳的字串不要再函式結束時被釋放掉,可以改用動態配置記憶體的方式:
01 /*file name: return_pointer_2.cpp*/ 02 03 #include<iostream> 04 #include<cstdio> 05 #include<cstdlib> 06 using namespace std; 07 char* test() 08 { 09 int i; 10 char a[5]; 11 char *ptr = (char*)malloc(sizeof(a));//ptr 指到一塊動態配置的記憶體,沒有被釋放前資料不會消失 12 for(i = 0; i < 5; i++)//先把剛配置的記憶體的值歸零 13 *(ptr+i) = 0; 14 *(ptr+0) = 'A'; 15 cout << "函式輸出: "; 16 for(i = 0; i < 5; i++) 17 printf("%d ", *(ptr+i)); 18 cout << endl; 19 return ptr; 20 } 21 int main() 22 { 23 char *name; 24 name = test(); 25 int i; 26 cout << "回傳後輸出: "; 27 for(i = 0; i < 5; i++) 28 printf("%d ", *(name+i)); 29 cout << endl; 30 free(name);//^釋放前 ˇ釋放後 31 cout << "釋放後輸出: "; 32 for(i = 0; i < 5; i++) 33 printf("%d ", *(name+i)); 34 }執行結果:
函式輸出: 65 0 0 0 0
回傳後輸出: 65 0 0 0 0
釋放後輸出: 96 24 -39 0 -64
return_pointer_2.cpp中把ptr改成指向一個動態配置的記憶體,在釋放前資料不會消失,所以函式結束後在主程式能得到所配置的5 Bytes的資料。
對於return_pointer_1.cpp主程式無法得到函式中ptr指到的陣列的值,可以改成以址傳遞、無回傳值的方式:
01 /*file name: return_pointer_3.cpp*/ 02 03 #include<iostream> 04 #include<cstdio> 05 using namespace std; 06 void test(char *ptr) 07 { 08 int i; 09 for(i = 0; i < 5; i++) 10 *(ptr+i) = 0;//全部歸 0,用來比對主程式中的初始化 11 cout << "函式內:\n" << "值: "; 12 for(i = 0; i < 5; i++) 13 printf("%d ", *(ptr+i)); 14 cout << endl; 15 cout << "址: "; 16 for(i = 0; i < 5; i++) 17 printf("%p ", (ptr+i)); 18 cout << endl; 19 } 20 int main() 21 { 22 char a[5] = "HaHa";//用來比對呼叫函式之後的結果 23 test(a); 24 int i; 25 cout << "回傳後:\n" << "值: "; 26 for(i = 0; i < 5; i++) 27 printf("%d ", a[i]); 28 cout << endl; 29 cout << "址: "; 30 for(i = 0; i < 5; i++) 31 printf("%p ", &a[i]); 32 cout << endl; 33 }執行結果:
函式內:
值: 0 0 0 0 0
址: 0071FCA0 0071FCA1 0071FCA2 0071FCA3 0071FCA4
回傳後:
值: 0 0 0 0 0
址: 0071FCA0 0071FCA1 0071FCA2 0071FCA3 0071FCA4
return_pointer_3.cpp中,我們把a陣列的初始位置傳進函式,把值全部歸零,因為使用的記憶體空間是主程式的,所以在主程式結束前沒有生命週期的問題,跟return_pointer_2.cpp比起來,return_pointer_2.cpp是在函式內動態配置記憶體,return_pointer_3.cpp是使用主程式靜態配置的記憶體,都可以達到讓主程式得到正確的字串。
沒有留言:
張貼留言