c++ 指標小計
什麼時指標:指標是存入指定資料類型地址的一種變數,void * 指標類型的指標可以存放任何資料類型的指標。
定義和聲名指標變數:由資料類型後跟星號,再跟隨指標變數名組成。如 int *ip;指標在使用前,要進行初始化。
如int count =10;int *count = &count;如果忘記了給指標賦值是非常危險的。因為指標在沒有初始化時存放的是一個隨機的地址,此時如果給指標賦值(*count = 20;)是把20賦到了記憶體中的隨機位置,因此很可能破壞系統中的另一變數甚至修改棧中的函數返回地址。
"*":此符號的用法很多,*放在可執行語句中的指標之前,稱為間接引用操作符(可取出指標指向變數的值),*放在指標定義中,稱指標定義符(用於定義一個指標變數)*放在運算式中用於乘法運算子,且不能放在非指標變的前面。
指標的地址:指標是變數是變數也有地址,我們可以用&取地址符取得指標變數的地址,如:int *ip = &count;用&ip得到指標變數的地址。
指標是強型別化的:給指標賦值,不但必須是一個地址,而且應該是一個與該指標類型相符的變數或常量的地址。
指標運算:指標只能用於加,減運算。
數組名稱也是一個指標常量,如int a[100];中a == &a[0]的。即是數組第一個元素的地址。
指向常量的指標:在指標定義語句的類型前加const,表示指向的對象是常量。如:const int *pi=&count;(*pi指標指向的值不能修改,但是地址可以被修改,即可以將指標指向另一個常量)
指標常量:在指標定義語句的指標名前加const,表示指標本身是常量。如 int * const pi="1234";int * const pi =&count;在定義指標常量時必須初始化,且不能作為左值進行操作,但是允許修改間接訪問值,即*pi = "3333";或者*pi = &pi2;
指向常量的指標常量:是指向常量的指標和指標常量的組合,它擁有兩者的功能。即指標指向的值不能修改,且地址也不能被修改。如:const int * const pi=&cont
資料、字元與指標:
傳遞數組的指標性質:如果將一個數組作為參數傳遞到函數中,則在棧上定義了一個指標,可以對該指標進行遞增,遞減操作。由於是以指標的行式傳
入則我們不能用sizeof(arr)/sizeof(*arr)的行式得到數組中的元素個數。所以必須將數組的元素個數一併傳入函數內。下面是一個例子:
#include <iostream>
void Sum(int array[],int n)
{
int sum =0;
for(int i=0;i<n;i++)
{
sum += *array;
array++;
}
cout << sum <<endl;
}
void main()
{
int a[10] = {1,2,3,4,5};
Sum(a,5);
}
將指標做為參數傳遞到函數可以返回多個值。由於是以指標的行式傳遞的,所以函數參數接收的是一個地址如果修改此地址所指向的內容,則在函數外部是可見並且是與函數內所做的修改是同步的。
例如:函數定義為 void swap(int *x,int *y);調用時則為swap(&a,&b);在函數內以*x,*y訪問值。
指標函數:傳回型別為指標的函數為指標函數。注意不要把在函數內部的局部變數的地址做為傳回值,因為在函數內部的局部變數在函數完成時就將結
束其自已的生命週期,這樣當把它做為函數的傳回值時在函數外部通過返回的指標訪問其值時,此值的生命已結束顧得不到想要的結果。例子如下:
#include <iostream>
int * GetInt(char * str)
{
int value = 20;
}
void somefn(char * str)
{
int a=40;
cout <<str<<endl;
}
void main()
{
int * pr=GetInt("input a value:");
cout <<*pr<<end;
somefn("It is uncertain.");
cout <<*pr<<endl;
}
void 指標是空類型指標,它不指向任何類型,即void指標僅僅只是一個地址。所以空類型指標不能進行指標運算(pi++),也不能進行間接引用(*pi)
字元數組和字元常量
字元數組:char buffer[] ="helle";
字元常量:"good" 字元常量的類型是指向字元的指標(字元指標char * ),兩個同樣字元組成的字串常量的地址是不相等的,且兩個字串的比較其實是兩個字串的首地址的比較。要比較內容可以用strcmp()函數進行比較。
字元指標:其實字串常量,字元數組名都是字元指標。輸出字元指標就是輸出字串,所以輸入如 char *pc;pc="hello";cout <<pc;則顯示hello字串。輸出字元指標的間接引用就是輸出當前地址所指的單個字元。在C++中不能直接對字元數組賦值,因為數組名是一個常量指標,不能做為左值。如:char buffer[10]; buffer = "hello";是錯誤的。我們可使用strcpy(char * dest,const char * src);函數進行賦值。
指標數組:一個數組中的每一個元未素也都是一個指標的話,我們則稱其為指標數姐。如:char *p[] = {"aaaa","bbbb","cccc"};
指向指標的指標即二級指標,指標數組是一個二級指標,如:char *pc[] = {"aaaa","bbbb","cccc"}; char **ppc=pc;
NULL指標是不指向任何地方的指標,通常用於右值。如char ch = NULL; char *pc = NULL;NULL與void * 不同,NULL是一個值,一個指標值,任何類型的指標都可以賦予該值。而void *是一種類型,是一種無任何類型的指標。
函數指標:在程式過行中,全域變數存放在Data區,局部變數存放在棧區,動態變數存放在堆區。函數代碼是程式演算法指令部分,它們同樣也點有記憶體空間,存放在代碼(code)區。每個函數都有地址。指向函數地址的指標稱為函數指標。
函數指標的定義:int (*func)(char a,char b);此定義了一個名叫func的函數指標變數,在使用是必須指向一個指以上定義相同的傳回型別和參數的函數地址,如 int fn1(char x,char y){cout <<"dddddddd";} int (*fn2)(char a,char b);通過以上定義我們就可以將函數fn1的地址賦給fn2 如 fn2=fn1;這樣可以調用int c = fn2('a','b');或者int c = (*fn2)('a','b');來調用fu1函數;還可用typedef來簡化函數指標的定義,如type int (*Handle)(char a,char b); 這時的Handle是一個函數指什類型,該指標類型中的指標指向一個函數,Handle不是指標變數,只是一個指標類型,通過Handle fn2;可定義一個指標變數之後可以向上面那樣調用fn2 = fn1;int c = fn2('a','b');int c = (*fn2)('a','b');
另外函數針還可以構成指標數組。我們來看一個列子。
#include <iostream>
typedef void (*MenuFun)();
void f1(){cout <<"good\n";}
void f2(){cout <<"better!\n";}
void f3(){cout <<"best!\n";}
MenuFun fun[] = {f1,f2,f3}
void main()
{
int choice;
do
{
cout <<"1--display good\n";
cout <<"2--display better\n";
cout <<"3--display best\n";
cout <<"0--exit\n";
cout <<"Enter your choice:";
cin >> choice;
switch(choice)
{
case 1:fun[0]();break;
case 2:fun[1]();break;
case 3:fun[2]();break;
case 0:return;
defaut:cout <<"you entered a wrong key.\n";
}
}while(choice)
}
函數指標還可以做為傳回型別:如typeof int (*SIG)();typeof void (*SIGARG)(); SIG signal(int x, SIGARG sigarg){sigarg();return sigarg;}