看板 Knuckles_note
作者 標題 [C++] Call by Address (Call by Pointer)
時間 2010年03月07日 Sun. AM 12:15:06
看完上一篇 Call by Value 後
我們知道了一般傳址呼叫的問題就是輸出值只能有一個
而我們希望在副程式中,可以修改主程式變數的值
方法就是: function 的輸入值由原本變數的值 改為 變數的記憶體位址
不過記憶體位址,其實也只是個整數值,所以這也是 Call by Value 的一種
只是 Value 是指 Pointer 的值,所以也有人稱這方法為 Call by Pointer
先介紹一下指標的用法
^L指標簡介
指標的定義很簡單,就是用來儲存記憶體位址的變數
跟一般變數沒兩樣,只是他是用來存位址而已
^L指標簡介
指標的定義很簡單,就是用來儲存記憶體位址的變數
當我們宣告一個普通的整數變數時
在記憶體中長這樣:
Address
Name Value
int a = 5;
0x00000100 a 5
↑
位址是系統自動給定的,不能自己設
0x開頭代表後面的數字使用16進位
若是32位元的電腦,位址最大值為 32 bits = 4 bytes
所以用16進位會有8位數 (2^32 = 16^8)
之後為了方便解說,省略前面的0 → 0x100
^L指標簡介
指標的定義很簡單,就是用來儲存記憶體位址的變數
當我們宣告一個普通的整數變數時
在記憶體中長這樣:
Address
Name Value
int a = 5;
0x100 a 5
如果我們想要把 a 的位址存起來
就要先宣告一個指標變數
↙因為前一個變數 int,大小為 4 bytes
int* p_a;
0x104 p_a
↑
雖然指標存的都是記憶體位址
但為了要記錄指向位址的大小,所以也有型態之分
這邊因為是用來指向一個 int 變數的指標,所以用 int*
代表p_a用來存一個int變數的位址
^L指標簡介
指標的定義很簡單,就是用來儲存記憶體位址的變數
當我們宣告一個普通的整數變數時
在記憶體中長這樣:
Address
Name Value
int a = 5;
0x100 a 5
如果我們想要把 a 的位址存起來
就要先宣告一個指標變數
int* p_a;
0x104 p_a
然後使用取址運算子 & 取得 a 的位址後存進 p_a
p_a = &a;
0x104 p_a 0x100
^L指標簡介
指標的定義很簡單,就是用來儲存記憶體位址的變數
當我們宣告一個普通的整數變數時
在記憶體中長這樣:
Address
Name Value
int a = 5;
0x100 a 5
如果我們想要把 a 的位址存起來
可以簡寫成這樣:
int* p_a = &a;
0x104 p_a 0x100
^L指標簡介
指標的定義很簡單,就是用來儲存記憶體位址的變數
當我們宣告一個普通的整數變數時
在記憶體中長這樣:
Address
Name Value
int a = 5;
0x100 a 5
如果我們想要把 a 的位址存起來
可以簡寫成這樣:
int* p_a = &a;
0x104 p_a 0x100
當我想要利用指標 p_a 存取 a 的值時,就利用取值運算子 *
int b = *p_a; // 讀取 a 的值
0x108 b 5
*p_a = 10; // 寫入 a 的值
0x100 a 10
^L指標簡介
指標的定義很簡單,就是用來儲存記憶體位址的變數
重新復習一下
Address Name Value
宣告一個整數變數
int a = 5;
0x100 a 5
宣告一個指標變數
int* p_a;
0x104 p_a
取得一個普通變數的位址
p_a = &a;
0x104 p_a 0x100
利用指標讀取變數的值
int b = *p_a;
0x108 b 5
利用指標寫入變數的值
*p_a = 10;
0x100 a 10
^L指標簡介
指標的定義很簡單,就是用來儲存記憶體位址的變數
總之,就是記得三個東西
宣告指標用 int* 就是指向變數的型態再加個 *
對變數取址用 &
取得變數的位址
對指標取值用 * 取得指向變數的值
接著來看我們要怎麼用指標來解決上一篇提到的 swap() 問題
^LCall by Address
#include <iostream>
這是 Call by Value 的寫法
using namespace std;
void swap(int,int);
int main()
{
int a=3,b=4;
swap(a,b);
cout << "a=" << a
<< ",b=" << b << endl;
return 0;
}
void swap(int a, int b)
{
int c = a;
a = b;
b = c;
}
^LCall by Address
#include <iostream>
1. 副程式的輸入值改為變數的位址
using namespace std;
void swap(int,int);
int main()
{
int a=3,b=4;
swap(&a,&b);
← 利用取址運算子 &,傳入 a,b 的位址
cout << "a=" << a
<< ",b=" << b << endl;
return 0;
}
void swap(int a, int b)
{
int c = a;
a = b;
b = c;
}
^LCall by Address
#include <iostream>
2. 副程式輸入變數的型態改為 指標
using namespace std;
void swap(int*,int*);
← swap() 將傳入兩個指標
int main()
{
int a=3,b=4;
swap(&a,&b);
← 利用取址運算子 &,傳入 a,b 的位址
cout << "a=" << a
<< ",b=" << b << endl;
return 0;
}
void swap(int* p_a, int* p_b)
← swap() 宣告兩個指標 p_a, p_b
{
int c = a;
a = b;
b = c;
}
^LCall by Address
#include <iostream>
3. 副程式中,利用指標來存取指向變數的值
using namespace std;
void swap(int*,int*);
← swap() 將傳入兩個指標
int main()
{
int a=3,b=4;
swap(&a,&b);
← 利用取址運算子 &,傳入 a,b 的位址
cout << "a=" << a
<< ",b=" << b << endl;
return 0;
}
void swap(int* p_a, int* p_b)
← swap() 宣告兩個指標 p_a, p_b
{
int c = *p_a;
*p_a = *p_b;
← 將指標加上取值運算子 * 來存取main()的變數值
*p_b = c;
}
^LCall by Address
#include <iostream>
using namespace std;
在程式還沒有執行時
void swap(int*,int*);
在記憶體中長這樣:
int main()
main() 的變數:
{
Address Name Value
int a=3,b=4;
0x100 a 3
swap(&a,&b);
0x104 b 4
cout << "a=" << a
<< ",b=" << b << endl;
return 0;
}
void swap(int* p_a, int* p_b)
swap() 的變數:
{
Address Name Value
int c = *p_a;
0x200 p_a
*p_a = *p_b;
0x204 p_b
*p_b = c;
0x208 c
}
^LCall by Address
#include <iostream>
using namespace std;
當程式呼叫了 swap() 時
void swap(int*,int*);
int main()
main() 的變數:
{
Address Name Value
int a=3,b=4;
0x100 a 3 ──┐傳出 0x100
→
swap(&a,&b);
0x104 b 4 ──┼───┐傳出 0x104
cout << "a=" << a
│
│
<< ",b=" << b << endl;
│
│
│
│
return 0;
│
│
}
│
│
│
│
void swap(int* p_a, int* p_b)
swap() 的變數:
│
│
{
Address Name Value
│
│
int c = *p_a;
0x200 p_a 0x100 ←┘
│
*p_a = *p_b;
0x204 p_b 0x104 ←────┘
*p_b = c;
0x208 c
}
^LCall by Address
#include <iostream>
using namespace std;
當 swap() 執行完時
void swap(int*,int*);
int main()
main() 的變數:
{
Address Name Value
int a=3,b=4;
0x100 a 4
→
swap(&a,&b);
0x104 b 3
cout << "a=" << a
<< ",b=" << b << endl;
return 0;
}
void swap(int* p_a, int* p_b)
swap() 的變數:
雖然 swap() 無法存取 main() 的 a,b
{
Address Name Value
但因為有取得 a,b 的位址
int c = *p_a;
0x200 p_a 0x100 所以可以利用取值運算子 *
*p_a = *p_b;
0x204 p_b 0x104 存取指向變數的值
→
*p_b = c;
0x208 c 3 所以 main() 中a,b的值就被 swap() 改掉了
}
^LCall by Address
#include <iostream>
using namespace std;
void swap(int*,int*);
int main()
main() 的變數:
{
Address Name Value
int a=3,b=4;
0x100 a 4
swap(&a,&b);
0x104 b 3
→
cout << "a=" << a
<< ",b=" << b << endl;
執行結果顯示: a=4,b=3
成功的將 a,b 的值互換了
return 0;
}
void swap(int* p_a, int* p_b)
swap() 的變數:
{
Address Name Value
int c = *p_a;
0x200 p_a
*p_a = *p_b;
0x204 p_b
*p_b = c;
0x208 c
}
^LCall by Address
#include <iostream>
懂是懂了,可是用指標當輸入變數好麻煩
using namespace std;
呼叫的時候要取址,使用的時候要取值
感覺很容易就會寫錯,有沒有更好的方法呢?
void swap(int*,int*);
當然是有囉,就是下篇要講的 Call by Reference
int main()
{
int a=3,b=4;
swap(&a,&b);
cout << "a=" << a
<< ",b=" << b << endl;
return 0;
}
void swap(int* p_a, int* p_b)
{
int c = *p_a;
*p_a = *p_b;
*p_b = c;
}
--
※ 來源: DISP BBS (http://disp.twbbs.org)
※ 作者: Knuckles 來自: 114.45.56.117 時間: 2010-03-07 00:15:06
※ 編輯: Knuckles 來自: 114.45.56.117 時間: 2010-03-07 03:02:18
※ 編輯: Knuckles 來自: 114.45.56.117 時間: 2010-03-07 03:08:45
※ 編輯: Knuckles 來自: 114.45.56.117 時間: 2010-03-07 03:09:29
※ 編輯: Knuckles 來自: 118.168.102.236 時間: 2010-03-07 15:36:53
※ 編輯: Knuckles 來自: 118.168.102.236 時間: 2010-03-07 16:24:56
※ 看板: KnucklesNote 文章推薦值: 3 目前人氣: 0 累積人氣: 9357
回列表(←)
分享