1. 程式人生 > >關於學習NDK基礎知識這些就夠了(二)

關於學習NDK基礎知識這些就夠了(二)

一、指標的運算
指標的型別:
指標有型別,地址沒有型別
地址只是開始的位置,型別讀取到什麼位置結束

1、常量指標:
首先它是一個指標,常量只是用來修飾指標的定語。其定義如下:

char const * cp; 
char a='a'; 

如何識別呢?根據右結合優先,先是優先,所以這個cp變數是一個指標,然後是const修飾,所以這是一個常量指標。即指向常量的指標。

cp=&a; //正常語法 
*cp=a; //錯誤語法,因為其指向的值是一個常量 

2、指標常量:
首先它是一個常量,指標是用來修飾常量的,即常量的值為一個指標地址。


char
* const cp; char a='a';

如何識別呢?根據右結合優先,先是const優先,所以這個cp變數是一個常量,然後是*修飾const,所以這是一個指標常量。

cp=&a; //錯誤語法,因為其地址為是一個常量
*cp=a; //正確,地址所指向的內容是一個普通字元

注意和上邊區分開

3、指標陣列:
首先它是一個數組,指標是用來修飾陣列內容的,表示什麼樣的陣列 :即存放指標的陣列

char *arr[3] = {"1","123","345"}; 

如何識別,因為[]的優先順序大於,所以先是定義為一個數組,而後由來修飾這個數

printf("arr0%c
\n"
,*arr[0]); printf("arr1%s\n",arr[1]);

4、陣列指標:
首先它是一個指標,陣列是修飾指標的,即指向陣列的指標。

char (*p)[3];  //申明時不能同時初始化 
char arr[3] = {'1','4','7'}; 
p=&arr; //指向陣列的首地址,同時指標的型別是char * [3] 型別的,即加1操作後為sizeof(char [3])


如何識別:因為這次添加了一個顯示優先,所以這次先是一個指標,而後[]修飾指標

printf("%c\n",(*p)[0]);  //先取arr的首地址,再根據這個地址取陣列內容 
printf
("%c\n",(*p)[1]); printf("%c\n",(*p)[2]); printf("%c\n",*((char*)p+0)); //先轉換為char指標,再取值 printf("%c\n",*((char*)p+1)); printf("%c\n",*((char*)p+2)); printf("%c\n",((char*)p)[0]); //先轉換為char指標,再取陣列的值,和第一個類似 printf("%c\n",((char*)p)[1]); printf("%c\n",((char*)p)[2]);

5、函式指標:
首先它是一個指標,函式是修飾指標的,即指向函式的指標。

char (*func)(void); //定義函式指標 
char test(void)  
{ 
return 'A'; 
} 
func = test;  //初始化賦值 
printf("test address: %p\n",test); 
printf("func address: %p\n",func); 
char ch = func();  //呼叫 
printf("%c\n", ch); 

例項:

int msg(char* msg,char* title){
    MessageBox(0,msg,title,0);
    return 0;
}
void main(){
    //msg();
    printf("%#x\n",msg);
    printf("%#x\n",&msg);
    //函式指標
    //函式返回值型別,函式指標的名稱,函式的引數列表
    int(*fun_p)(char* msg, char* title) = msg;
    fun_p("訊息內容","標題");

    getchar();
}

如何識別,同陣列指標一樣,因()的優先順序,所以這個定義首先是一個指標,而後才是對指標的描述,即一個指向函式的指標,其指向的函式也是規定的:即返回的是字元型別,不需要傳入引數

6、指標函式:
首先它是一個函式,指標修飾函式的返回型別,即一個返回指標的函式

char *func(void); 

如何識別,因為沒有擴弧,所以的優先順序沒有右邊的擴弧優先順序高,所以先是規定了一個函式,只是修飾返回值的

char *func(void) { 
  char *str = "test"; 
  return str; 
 } 
 void main() { 
  char *test = func();  
  printf("%s\n",test);  
} 

7、指標為什麼要有型別?
指標有型別,地址沒有型別
地址只是開始的位置,型別讀取到什麼位置結束

void main(){
    int i = 89;
    //int 型別的指標
    int *p = &i;
    double j = 78.9;
    //賦值為double型別變數的地址
    p = &j;
    printf("double size:%d\n", sizeof(double));
    printf("%#x,%lf\n",p,*p); //想通過4位元組讀取8位元組變數的值,是不行的    

    getchar();
}

8、指標型別轉換:

指標型別轉換是個有意思的東西,你可以把一個int型的指標轉換為char型別,然後再把char型別的指標轉換為int型;就像普通的字元和int型之間的轉換一樣。但指標轉換後其值沒有變,唯一變的東西就是指標的步長,即進行指標運算時的計算方式。當為char指標時其運算單位均以1個位元組為1個運算單位,而當為int指標時通常都是以4個位元組為1個運算單位。

9、指標算術:

根據上面的指標型別轉換介紹可知,不同的指標型別進行算術運算時其計算方式時不相同的,其不同之處就在於其步長的位元組數不同,而具體其步長為幾個位元組數是以其指標型別決定的,指向char的指標步長即為1。通常的指標運算有指標與數字的加減運算,相同型別的指標的減法運算,而且還要是指向同一個陣列的,不然意義不大。同理推得不同型別的指標進行運算意義更不大,甚至會報錯。
下面舉一個指標算術的例子,交換兩個變數值不利用額外變數
畢竟new關鍵字還是申請了額外的記憶體,雖然沒有申請變數,換湯未換藥



int *a,*b;   
a=new int(10);    //給指標賦值 
b=new int(20);    //a=0x00030828,b=0x00030840 
a=(int*)(b-a);    //a=0x00000006 
b=(int*)(b-int(a));  //b=0x00030828 
a=(int*)(b+int(a));  //a=0x00030840 

只是交換變數的話也可以:

int a = 4; 
int b = 5; 

*(((char*)&a)+1) = *((char*)&b); 
*((char*)&b)=*((char*)&a); 
*((char*)&a)=*(((char*)&a)+1); 
*(((char*)&a)+1)=0; 

例項:

void main(){
    //陣列在記憶體中連續儲存
    int ids[] = { 78, 90, 23, 65, 19 };
    //陣列變數名:ids就是陣列的首地址
    printf("%#x\n",ids);
    printf("%#x\n",&ids);
    printf("%#x\n",&ids[0]);
    //指標變數
    int *p = ids;
    printf("%d\n",*p);
    //指標的加法
    p++; //p++向前移動sizeof(資料型別)個位元組
    printf("p的值:%#x\n", p);
    //p--;
    printf("%d\n", *p);
    getchar();
}

10、NULL空指標

void main(){
    int i = 9;
    int *p = NULL;
    //p = &i;

    //空指標的預設值為0
    printf("%#x\n",p);
    //訪問記憶體地址0x000000作業系統不允許
    //p = 100; //作業系統不允許訪問
    printf("%d\n",*p);
    getchar();
}

通過指標給陣列賦值

void main(){
    int uids[5];
    //高階寫法
    //int i = 0;
    //for (; i < 5; i++){
    //  uids[i] = i;
    //}
    //早些版本的寫法
    int* p = uids;
    printf("%#x\n",p);
    int i = 0; //i是陣列元素的值
    for (; p < uids + 5; p++){
        *p = i;
        i++;
    }

    getchar();
}

11、多級指標(二級指標)

指標儲存的是變數的地址,儲存的這個變數還可以是一個指標變數
動態記憶體分配給二維陣列

void main(){
    int a = 50;
    //p1上儲存的a的地址
    int* p1 = &a;

    //p2上儲存的p1的地址
    int** p2 = &p1;

    //int*** p3 = &p2;

    printf("p1:%#x,p2:%#x\n",p1,p2);
    **p2 = 90;

    printf("%d\n",a);

    getchar();
}