指標的使用和運算
目錄
[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 p
和const int *p
以及int const *p
主要由*和const的相對位置區分,所以後兩者的意思是相同的
int *const p
即 指標是const,一旦得到了某個變數的地址,不能再指向其他變數。
int *const p=&i;//p是const
*p=26;//ok
p++;//error
const int *p
和int 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比較保險(注意大寫)