2016年8月28日 星期日

指標的基本用法

指標

基本概念
  • 符號意義
副程式
  • 為何副程式必須導入指標
  • 副程式引入處指標與陣列不同
  • 如何從副程式得到指標長度
  • 間接定址與直接定址
  • 為何需要指標的指標
 指標類型
  • 指標的指標
  • 結構指標
  • 虛無指標
下周分享內容:如何有效率的編程

基本概念

符號意義

記住兩句話 &找地址 *找數值  
int i=1 程式初始化配置記憶體
給變數i使用並在裡面儲存數值1
可以透過 &i 查找記憶體地址
int* p=&i 創建一個指標,並告知
編譯器這個用來儲存儲存整數,再來存入
i 的地址
可以透過 *i 查找記憶體地址內的數值
關於指標的創建,請記住這句話
告知編譯器這個用來儲存儲存整數
後續會繼續討論,這裡先討論兩個區別
int* iint *i 有什麼區別呢
在編譯器內他們是等價的,但建議使用前者
的方式宣告,更容易閱讀,可以想像
把他們當成另一個型態 int*
這樣更容易閱讀對吧XDD
那什麼時候才需要用到把星號放到後面呢?
int* i, j; 你覺得後面的j是什麼型態呢
直覺得˙會把它看成 int* 型態但其實他們是
等價於 int* i; int j
這時候我會建議你都把他們放後面吧
int *i, *j; or int *i ,j;
這樣就更容易閱讀了

副程式

為何副程式必須導入指標

有了前者得概念,現在來出一到小題
如何使用副程式修改變數
簡單的來形容主程式內有一個變數
我要呼叫一個副程式修改i的數值
int i=0;
modify();
如何實做呢 https://goo.gl/2EMGo3

副程式引入處指標與陣列不同

fun(int* arr);

fun(int arr[4]);
用途上來看最主要大概差異在
前者沒有把數字定死,想傳幾個都可以傳
即便是後者,你傳入一個長度是5的陣列能然能取到
第5個的數值,這純粹只是運氣好,第5個的數值
只是因為宣告時記憶體是連續的,運氣好可以讀到
程式如果複雜了,並不能保證他不會修改

如何從副程式得到指標長度

通常來說都會在下標的第[0]個儲存長度
這可以節省運算時間,也讓你更好操作
C++可以透過樣板取得取得長度
template<size_t N>
void arr_len(int (&arr)[N]) {
    std::cout << "sizeof = " << sizeof(arr) << " / ";        
    std::cout << sizeof(arr[0]) << std::endl;
    std::cout << "len = arr[" << N << "]" << std::endl;
}
樣板會干擾到拆分程式,還是建議採用前者

間接定址與直接定址

假設有一個二微陣列是 [2][2]
那麼在記憶體上第三個是 [1][0]
輸入 [1][0] 在操作上必須找兩次,
先找到[0]的地址再去查找地址的數值
速度上會略低,如果宣告成一微陣列
自己手動算出[2][2]是第3個
效率上會來的好一些,在操作上也較容易

為何需要指標的指標

  1. 存取動態二維陣列
  2. 副程式拆解上的需求
這可能有點難形容,兩者其實
也差不都在形容同一件事情
直接看代碼或許會比較好理解
核心代碼
imch imgraw::cubicInterpolate (imch* p, double x) {
    double temp = (double)(p[1] + 0.5 * 
        x*(p[2] - p[0] +x*(2.0*p[0] - 5.0*p[1] + 4.0*p[2] - 
            p[3] + x*(3.0*(p[1] - p[2]) + p[3] - p[0]))));
    return (imch)temp;
}
用來控制核心代碼的驅動
imch imgraw::bicubicInterpolate (imch** p, double y, double x) {
    imch* arr = new imch[4];
    for (int i = 0; i < 4; ++i)
        arr[i] = cubicInterpolate(p[i], x);
    return cubicInterpolate(arr, y);
}
如果沒有將核心代碼拆分出來,核心代碼必須重複5次

指標的指標

動態二維陣列的應用
// 創建
int** ptr = new int* [2];
for (int i = 0; i < 2; ++i)
    ptr[i] = new int [2];

// 釋放
for (int i = 0; i < 2; ++i)
    delete [] ptr[i];
delete [] ptr;

結構指標

結構
struct node{
    int i;
};
結構指標要用->去指向
node a, *b;
b = &a;
a.i = 1;
cout << b->i << endl;
return 0;

虛無指標

這應該很少會用到,但如果你要把程式寫好
寫得足夠嚴謹,就必須得用他,
很多底層的代碼,都是這樣定義的
//接收不同型態的資料
void pri_int(void* data){
    int temp=(int)*data;
    cout << "temp=" << temp << endl;
}
這個副程式將可接受各種型態的指標
最終cast成整數的樣貌,印出

沒有留言:

張貼留言