2012年7月23日 星期一

指標變數與函數指標筆記

指標變數wiki的定義:

In computer science, a pointer is a programming language data type whose value refers directly to (or "points to") another value stored elsewhere in the computer memory using its address.
簡單來說 指標變數就是指出資料存在哪個記憶體位址,也就是指標變數就是一個記憶體位置記錄器,如下圖(轉至wiki)




指標的宣告:

不同資料類型代表不同大小 需搭配不同的指標
int a=100;
int *a_ptr;
a_ptr=&a; //將a 取位址放到指標 a_ptr
char b=200;
char *b_ptr;
b_ptr=&b; //將b 取位址放到指標 b_ptr

指標也是一個變數 所以他存的地方也有他的記憶體位址, 因此可以使用指標的指標
int a=100;
int *a_ptr;
int **a_ptr_ptr;
a_ptr=&a; //將a 取位址放到指標 a_ptr 
a_ptr_ptr=&a_ptr; //將a 取位址放到指標 a_ptr

附註:"&"為取址運算子,利用他可取得變數之記憶體位址
             另外" * "也有人稱為取值運算子,可取得該記憶體位址的值
             在該範例 *a_ptr_ptr 就為 a_ptr 的值而 a_ptr 的值就是a的記憶體位址
            **a_ptr_ptr 就為 a 的值

當需要很多指標時可使用指標陣列
int a[10];
int *a_ptr[10];
a_ptr[0]=(a+0);  //a為矩陣起始記憶體位址
a_ptr[1]=(a+1);  //每+1,記憶體就前進一個資料型態的記憶體長度
....

 其他指標宣告
int *ptr1, ptr2;.//只有ptr1是指標
int *ptr1, *ptr2;.//都是是指標 
void *ptr1 //宣告的指標不含型別,只用來持有位址資訊,不可用*運算子提取值  
const int *ptr1 //指標ptr1不可變更

//口訣配合*()[]的優先權:()[]是第一優先權左結合,而*是第二優先權右結合
//看見[]就說array[] of
//看見*就說pointer to
//看見變數後面的()就說function() returning

char *x;        // x: a pointer to char
char x[3];      // x: an array[3] of char
char x();       // x: a function() returning char
char *x[3];     // x: an array[3] of pointer to char
char (*x)[3];   // x: a pointer to array[3] of char
char **x;       // x: a pointer to pointer to char
char *x();      // x: a function() returning pointer to char
char *x()[3];   // x: a function() returning array[3] of pointer to char
char (*x[])();  // x: an array[] of pointer to function() returning char
char (*x())();  // x: a function() returning pointer to function() returning char
char (*(*x)[])(int, int); // x: a pointer to array[] of pointer to function(int,int) returning char
指標的操作:

 已經取得了記憶體位置,當將某個值指定給*ptr時,該記憶體位置的值也會跟著改變,
     相當於告訴程式,將值放到ptr所指向的記憶體位址
int a=100;
int *a_ptr;
a_ptr=&a; //將a 取位址放到指標 a_ptr
*a_ptr=300;//此舉就是將300裝到a的記憶體位址
 指標與二維陣列
char aaa[2][3]={{1,2,3},{6,7,8}}; //a本身為一個指標的指標
printf("%d\n",*(aaa+0));
printf("%d\n",**(aaa+0));//要取值兩次才能取到值

//所以若要直接以aaa指標的指標操作的話此陣列依位址由小到大為
*(*(aaa+0)+0)=1  //aaa[0][0]
*(*(aaa+0)+1)=2  //aaa[0][1]
*(*(aaa+0)+2)=3  //aaa[0][2]
*(*(aaa+1)+0)=6  //aaa[1][0]
*(*(aaa+1)+1)=7  //aaa[1][1]
*(*(aaa+1)+2)=8  //aaa[1][2]

//但若使用指標變數取aaa第一個位址,必須將陣列攤開成一維陣列
char *ptr
ptr=&aaa[0][0]; //取陣列第一個位址
//此陣列依位址由小到大為 
*( ptr +0)=1 //aaa[0][0]
*( ptr +1)=2 //aaa[0][1]
*( ptr +2)=3 //aaa[0][2]
*( ptr +3)=6 //aaa[1][0]
*( ptr +4)=7 //aaa[1][1]
*( ptr +5)=8 //aaa[1][2]
函數指標:

 函數指標
程式在執行時,函式在記憶體中也佔有一個空間,函式名稱就為指向該空間位址的參考名稱當呼叫函式名稱時,程式就會去執行該函式名稱所指向的記憶體空間中的指令

 函數指標宣告與使用
一個函式型態由傳回值型態與參數列決定,不包括函式名稱,一個函式指標可指向具有相同型態的函式,也就是具有相同傳回值型態和參數列的函式。

//宣告
int function1(int,int);
int function1(int,char);//重載函式
int (*funcPtr1)(int int);
int (*funcPtr2)(int char);//重載函式佔有不同的空間,必須對應到相同參數型態的函式
//使用
funcPtr1=function1;//提取function1指標
funcPtr2=function1;//前面已宣告 程式可以判斷是哪個重載函式
funcPtr1(100,2000);//執行
funcPtr1(100,200);//執行


函數指標應用例:多個指令利用指標排程
void func1(void);//多個指令要執行
void func2(void); 
void func3(void); 
...
void(*funcPrt)(void)//函式指標
void(*funcPrt_Queue)[COMSize](void)//函式指標陣列 儲存指令隊列
//執行
if(time<=200)&&(time>0)//在第0ms~100ms執行指令
{
funcPrt=funcPrt_Queue[COMIndex]; //提取排到的函式指標
funcPrt();//執行
}
//其他函式void XXX(void)
{
...
funcPrt_Queue[QueueIndex]=func1;//func1隊列入待執行
}
void YYY(void)
{
...
funcPrt_Queue[QueueIndex]=func2;//func2隊列入待執行
}
 函數指標應用例:快速排序法(轉自http://caterpillar.onlyfun.net/Gossip/index.html)
sort.h
typedef bool (*CMP)(int, int);//定義CMP 讓程式更好閱讀

void swap(int&, int&);
bool larger(int a, int b);
bool smaller(int a, int b);
void sort(int*, int, CMP);//原本為void sort(int*, int, bool (*compare)(int, int));

sort.cpp
#include "sort.h";

void swap(int &a, int &b)
{
    int t = a; 
    a = b; 
    b = t;
}
bool larger(int a, int b) 
{
    return a > b;
}
bool smaller(int a, int b) 
{
    return a < b;
}
void sort(int* arr, int length, bool (*compare)(int, int))
 { 
    int flag = 1; 
    for(int i = 0; i < length-1 && flag == 1; i++) 
      { 
        flag = 0; 
        for(int j = 0; j < length-i-1; j++) 
           { 
            if(compare(arr[j+1], arr[j]))
               { 
                swap(arr[j+1], arr[j]); 
                flag = 1; 
            } 
        } 
    } 
}

main.cpp
#include "iostream"
#include "sort.h"
using namespace std; 
int main() 
{ 
    int number1[] = {3, 5, 1, 6, 9};
    sort(number1, 5, larger);
    int number2[] = {3, 5, 1, 6, 9};
    sort(number2, 5, smaller);
return 0;
}
參考:

http://caterpillar.onlyfun.net/Gossip/CppGossip/FunctionPointer.html

http://www.wretch.cc/blog/DreamYeh/721080

沒有留言:

張貼留言