2011年1月31日 星期一

【C++】指標與位址

C 語言和 C++ 都有提供操作計憶體的方法,亦為指標,也就是說你可以宣告依個變數來儲存記憶體位址

故指標變數所儲存的並不是值,而是值在記憶體中的位址,在 C++ 要取得變數的記憶體位址

變數的記憶體位址
可以加上一個 & 運算子,以下範例
#include 
using namespace std;
int main(void)
{
    int num = 10;
    double num1 = 10.1;
    count << "the value of num is" << num;
    count << "and it's address is " << &num <<"\n";  //印出 num 的記憶體位址
    count << "the value of num1 is" << num1;
    count << "and it's address is " << &num1 <<"\n";   //印出 num1 的記憶體位址
    system("pause");
    return 0;
}

指標變數的用法

那如何宣告指標變數並存取記憶體位址或是實際的值呢? 只要在變數名稱前面加個*就好了
至於要如何存取指標所指到的變數值和位址呢?

*pointer 就是取出指標變數所指到的變數之值
pointer 即是取出指標變數所指到的變數之記憶體位址
#include 
using namespace std;
int main(void)
{
    int number = 10;
    //法一
    int *pointer_INT1;  //宣告一個整向整數的指標
    pointer_INT1 = &number;   //將 number 的記憶體位址 assign 給 pointer_INT1 指標
    
    //法二 
    int *pointer_INT2 = &number; //宣告時順便給記憶體位址
    
    count << "Values of number : " << *pointer_INT1;  //印出 number 的值
    count << "Address of number : " << pointer_INT1;  //印出 number 的位址

    *pointer_INT1 = *pointer_INT1 + 1;  //把 pointer_INT1 指到的變數 number 的值 + 1
    
    count << "Values of number : " << *pointer_INT1;  //印出 number 的值
    
    system("pause");
    return 0;
}

動態配置記憶體
以上的記憶體宣告都是由編譯程式在編譯時其事先配置好的,如果想要動態配至一個位址
在 C 語言中是以 malloc() 函數來配置,而 C++ 還多了一個 new()

#include 
using namespace std;
int main(void)
{
    int *pointer = new int();  //動態配至一個記憶體位址給 pointer 這個指標變數
    *pointer_INT1 = 1000  //賦予值
    pointer_INT1 = &number;   //將 number 的記憶體位址 assign 給 pointer_INT1 指標

    count << "Values of number : " << *pointer;  //印出 pointer 指標指到的值
    count << "Address of number : " << pointer1;  //印出 pointer 指標的位址

    system("pause");
    return 0;
}

配置動態陣列
其實在C語言與C++裡陣列其實也是一種指標  所以在宣告陣列時也可以用指標變數去賦值

可是陣列再記憶體中的表示法為一聯串的配置,那這樣指標變數是指到哪一個?

其實是指到第一個的位址,也就是索引值為 0 的記憶體位址
#include 
using namespace std;
int main(void)
{
    int *pointer_arr = new int[3]; //配置陣列並讓指標變數 pointer_arr 指到
    
    //給一些值  跟一般陣列給值是一樣的作法
    pointer_arr[0] = 1;
    pointer_arr[1] = 2;
    pointer_arr[2] = 3;

    //印出指標陣列的第二個索引值的值 是 2
    count << "Value of pointer_arr[1] = " << pointer_arr[1] << "\n";  
    //將指標前進一個, 相當於將指標指到陣列第二個的位址
    pointer_arr = pointer_arr + 1;  
    //這時候 pointer_arr[0] 已經為 2 了, 因為上一行把指標往前推一格了
    count << "Value of pointer_arr[0] = : " << pointer_arr[0] << "\n";  
    //所以 pointer_arr[1] 就為 3 了
    count << "Value of pointer_arr[1] = : " << pointer_arr[1] << "\n";  

}

以上或許有點難理解 不過以下也是種辦法
int array[3] = {1, 2, 3};
int *pointer_arr1 = array; 和 int *pointer_arr2 = &array[0];

以上兩行是相同的意思,也就是上面那段程式要表達的

意思是 把陣列的第一個元素的記憶體位址 assign 給ㄧ個指標變數

由於陣列的記憶體位址是連續的,所以可以透過指標變數的加或減 達到在陣列間來回取值的目的

所以我們以上的 array 整數陣列  就可以以一般的表示法也可以用指標

array[0] 等同於 *(pointer_arr+0)
array[1] 等同於 *(pointer_arr+1)
array[2] 等同於 *(pointer_arr+2)

指標的危險性

在先前的範例中不論是動態配直記憶體位址或事變一時期配置,

對會讓指標予以一個變數的記憶體位址,如果今天這樣寫 

int *pointer;
*pointer = 123;

以上程式由於 pointer 並沒有先予以初始值,所以他現在很有可能是任何值

如果是 5000 則就會將 123 放到 5000 這個位址裡,而 5000 很可能有其他程式再使用

故以上的說法就是沒有宣告存放 123 的變數,而導致 pointer 沒有初始值

故在撰寫時請注意這點

沒有留言:

張貼留言