Preface:
在 變數 中曾經說過, 變數(Variable)提供一個有名稱的記憶體儲存空間,一個變數關係至一個資料型態、一個變數本身的值與一個變數的位址值. 變數資料型態決定了變數所分配到的記憶體大小;變數本身的值是指儲存於記憶體中的某個數值,而您可以透過變數名稱取得這個數值,這個數值又稱為 rvalue 或 read value;而變數的位址值則是指變數所分配到的記憶體之位置,變數本身又稱為 lvalue 或 location value.
Pointer and Address:
如果您想知道變數的記憶體位址為何,您可以使用 & 運算子, & 是「取址運算子」(Address-of operator),它可以取出變數的記憶體位址,例如:
- #include
- using namespace std;
- int main() {
- int var = 10;
- cout << "變數var的值:" << var
- << endl;
- cout << "變數var的記憶體位址:" << &var
- << endl;
- return 0;
- }
這個程式宣告了一個 int 整數變數 var,var 指向的記憶體位址是 0xbfee21cc,這是記憶體位址的16進位表示法,從 0xbfee21cc 後的 4 個位元組都是 var 所配置到的記憶體空間,現在這個空間中儲存值為10. 直接存取變數即直接對所分配到的記憶體空間作存取,指標(Pointer)則提供了間接性,指標可指向特定的記憶體位址,而不直接操作變數或物件,宣告 一個指標,使用以下的語法:
其中 type 是指標的型態,每一個指標都有一個相對應的型態,用以指出所指向的資料或物件之型態有所不同,編譯器根據指標型態來確定特定記憶體位址上的資 料如何解釋,以及如何進行指標運算(Pointer arithmetic),以下是幾個指標宣告的範例:
- int *iptr;
- float *fptr;
- char *cptr;
- #include
- using namespace std;
- int main() {
- int var = 10;
- int *ptr = &var ;
- cout << "變數var的位址:" << &var
- << endl;
- cout << "指標ptr指向的位址:" << ptr
- << endl;
- return 0;
- }
如以上的程式結果所示,您使用 & 來取出變數 var 所指向的記憶體位址,然後將這個位址指定給指標 ptr,因此 ptr 所儲存的值就與 &var 所取出的值相同.
指標擁有兩種操作特性,一是操作指標所儲存的位址,一是操作指標所指向位址之資料,或是操作指向的位址上之物件,您可以使用提取 (Dereference)運算子 * 來提取指標所指向位址的資料,例如:
- #include
- using namespace std;
- int main() {
- int var = 10;
- int *ptr = &var;
- cout << "指標ptr儲存的值:" << ptr
- << endl;
- cout << "取出ptr指向的記憶體位置之值:" << *ptr
- << endl;
- return 0;
- }
如果已經取得了記憶體位置,當將某個值指定給 *ptr 時,該記憶體位置的值也會跟著改變,相當於告訴程式,將值放到 ptr 所指向的記憶體位址,例如:
- #include
- using namespace std;
- int main() {
- int var = 10;
- int *ptr = &var ;
- cout << "var = " << var
- << endl;
- cout << "*ptr = " << *ptr
- << endl;
- *ptr = 20;
- cout << "var = " << var
- << endl;
- cout << "*ptr = " << *ptr
- << endl;
- return 0;
- }
如以上所表示的,當指標 ptr 所儲存的值與變數 var 所指向的記憶體位置相同時,當您對 *ptr 進行指定的動作時,就會將值直接存入該記憶體位置,因此再 透過變數 var 所取出的值也就改變了.
如果宣告指標但不指定初值,則指標指向的位址是未知的,存取未知位址的記憶體內容是危險的,例如:
- int *ptr;
- *ptr = 10;
- int *iptr = 0;
- int *ptr1;
- int* ptr2;
- int* ptr1, ptr2;
- int *ptr1, *ptr2;
- void* ptr;
- #include
- using namespace std;
- int main() {
- int var = 10;
- void *vptr = &var ;
- // 下面這句不可行,void型態指標不可取值
- //cout << *vptr << endl;
- // 轉型為int型態指標並指定給iptr
- int *iptr = reinterpret_cast<int*>(vptr);
- cout << *iptr << endl;
- return 0;
- }
您也可以使用舊風格的轉型語法,如下所示:
- int var = 10;
- void *vptr = &var ;
- // 轉型為int型態指標並指定給iptr
- int *iptr = (int*)(vptr);
- const int var = 10;
- var = 20; // error, assignment of read-only variable `var'
- int *ptr = &var; // error, invalid conversion from `const int*' to `int*'
- const int var = 10;
- const int *vptr = &var;
同樣的vptr所指向的記憶體中的值一但指定,就不能再改變記憶體中的值,您不能如下試圖改變所指向記憶體中的資料:
- *vptr = 20; // error, assignment of read-only location
- int x = 10;
- int y = 20;
- int* const vptr = &x;
- vptr = &x; // error, assignment of read-only variable `vptr'
- #include
- using namespace std;
- void foo(const int*);
- int main() {
- int var = 10;
- cout << "var = " << var << endl;
- foo(&var);
- cout << "var = " << var << endl;
- return 0;
- }
- void foo(const int* p) {
- int* v = const_cast<int*> (p);
- *v = 20;
- }
由於函式(Function)定義中傳入的指標使用const加上唯讀性,所以您不能對傳入的指標進行以下的動作:
- *p = 20; // error, assignment of read-only location
- int* v = const_cast<int*> (p);
- *v = 20;
- void foo(const int* p) {
- int* v = (int*) (p);
- *v = 20;
- }
* [C++] 標準類型轉換:static_cast, dynamic_cast, reinterpre...t, and const_cast. static_cast
沒有留言:
張貼留言