1. 程式人生 > >指標的使用和運算

指標的使用和運算

目錄
[TOC]

指標基礎

指標 即指向某資料的地址
指標是不可以int *p;然後*p=12;這樣賦值的,正確的應該是p=12;或是p=&i之類(p不是int類 而是int*類,當然不能直接給它賦int的值,它是地址啊)
例:

#include <iostream>
using namespace std;
int main()
{
    double i=100,j=200,k=300,d=10.9;
    double *pointer1,*pointer2=&d;
    pointer1=&i;
    //對指標的直接引用 
    cout<<pointer1<<endl;//0x6ffe28
//對指標的間接引用 cout<<*pointer1<<endl;//100 cout<<pointer2<<endl; //0x6ffe20 cout<<*pointer2<<endl;//10.9 j=*pointer1; cout<<j<<endl;//100 *pointer1=500; cout<<pointer1<<endl;//0x6ffe28 地址不變 cout<<i<<endl;//500 隨*pointer1一起改變
cout<<j<<endl;//100 pointer1指向的不是j的地址 所以當指標作為右值使用的時候就和普通賦值是一樣的(把pointer1指向的值賦給j),所以此處j的值不變 return 0; }

指標作函式引數

對於函式來說,傳入普通變數接收到值,傳入指標則接收到地址。為什麼要傳一個地址呢,因為比如一個structure,它可能很大,傳入地址就可以用比較少的位元組傳遞值給引數。傳入陣列時其實傳入的也是指標,int a[]和int *a是一樣的。

指標可以在函式中傳出多個變數

例:求陣列中元素的最大最小值
1.指標可以在函式中傳出多個變數

#include <iostream>
using namespace std;
void minmax(int a[],int len,int *min,int *max);
//此函式無返回值,void別手賤打成int,min和max雖然是引數,起的卻是帶出返回值的作用 
int main()
{
    int a[]={1,2,3,4,5,6,7,8,9,12,13,14,16,17,21,23,55};
    int min,max;
    //這裡的min和max也要宣告過,執行了函式之後值就被改變了
    minmax(a,sizeof(a)/sizeof(a[0]),&min,&max);
    //a後面不用加[],更不要忘了取址符,傳的是指標啊
    cout<<"min:"<<min<<",max:"<<max<<endl; 

}
void minmax(int a[],int len,int *min,int *max)
{
    *min=*max=a[0];
    for(int i=1;i<len;i++)
    {
        if(a[i]<*min)
            *min=a[i];
        if(a[i]>*max)
            *max=a[i]; 
    }
}

那如何實現自己輸入一個數組然後找到最大最小值呢?
稍微改一下上面的程式碼

#include <iostream>
using namespace std;
void minmax(int a[],int len,int *min,int *max);
int a[10000];
int main()
{
    int number,i=0;
    while(cin>>number)
    {
        a[i]=number;
        i++;
    }
    int min,max;
    minmax(a,sizeof(a)/sizeof(a[0]),&min,&max);
    cout<<"min:"<<min<<",max:"<<max<<endl; 

}
void minmax(int a[],int len,int *min,int *max)
{
    *min=*max=a[0];
    for(int i=1;i<len;i++)
    {
        if(a[i]<*min)
            *min=a[i];
        if(a[i]>*max)
            *max=a[i]; 
    }
}

注:這樣是錯誤的! 定義了全域性變數a[10000]後,儘管最後沒有cin10000個數據,但sizeof(a)還是10000*4,且未讀入的資料為0。把sizeof(a)/sizeof(a[0])換成i就可以了,本來sizeof(a)/sizeof(a[0])就是用來計算出陣列內元素個數的。
把陣列作引數,實際上也是指標。在**函式內部**sizeof(a)時,結果為4。

需要返回函式運算狀態時

函式返回(return)運算狀態(比如檔案操作中一般用-1或0表示沒有有效結果),而萬一有效結果就是-1或者0呢所以分開返回,則函式的運算結果通過指標引數返回。在C++中這也可以通過異常機制處理。

指標與const//c99only

注意區分 int *const pconst int *p以及int const *p
主要由*和const的相對位置區分,所以後兩者的意思是相同的
int *const p 即 指標是const,一旦得到了某個變數的地址,不能再指向其他變數。
int *const p=&i;//p是const
*p=26;//ok
p++;//error

const int *pint const *p即 所指是const,表示不能通過指標去修改那個變數(並不能使那個變數成為const)
const int *p=&i;
*p=26;//error
i=26;//ok
p=&j;//ok

void f(const int *x);
int a=15;
f(&a);//這樣a變成了const 就可以防止其在函式內部被修改

指標的運算

1.指標的地址線性遞增,且指標可比較(比較地址)
2.無論指向什麼地址,指標佔用空間的大小都是一樣的。
3.*(p+1)為移到下一個單元,移的距離為sizeof(型別)。例如char是1位元組,int是四位元組。如果p不指向連續的空間,則+1無意義。
4.兩指標可以相減,這時候無論是int還是char都代表1,也就是並不用管資料型別佔多少位元組(或者可以理解成地址差/sizeof(型別))
5.*p++ (++優先順序更高)
取出資料之後再移到下一個位置 經常用於陣列的遍歷
6.a為陣列,則int *p=a;相當於int *p=&a[0];
7.關於0地址。記憶體中有0地址,但指標不應該具有0值。因此可以用0地址來表示返回的指標無效等。NULL是一個預定定義的符號,表示0地址。有些編譯器不願意你用0來表示0地址,用NULL比較保險(注意大寫)