最近幾天複習了一下指標,總結記錄一下。
區分幾個概念:
指標陣列:指標的陣列,即本質是乙個陣列,陣列的每乙個元素是乙個指標。
陣列指標:陣列的指標,即本質是乙個指標,指標指向的物件必須是乙個陣列。
指標函式:返回指標的函式,本質是乙個函式,返回型別是乙個指標
int *p指標陣列,int(*p)陣列指標,int**p雙指標,int p二維陣列的比較
首先看一下二維陣列的記憶體分配情況
其記憶體是連續的,也就是說知道第乙個位址就能推算出任一乙個元素的位址。對於乙個二維陣列int[m][n]
&p[i][j]=&p[0][0]+(i*n+j)*sizeof(int *);所以sizeof(p)= m*n*sizeof(int *);
定義乙個二維陣列。可以看出h[0]是乙個陣列的首位址,而不是乙個陣列第乙個元素的位址。
sizeof(h[i]) = n*sizeof(int *)
int *p是乙個指標陣列,其記憶體分配情況如下圖所示。
p[i]之間是連續的,即&p[i]=p[0]+sizeof(int*)*i;但是&p[i][0],&p[i+1][0]之間是不連續的。也就是說&p[i+1][0]!= &p[i][0] + n*sizeof(int );sizeof(p) = n*sizeof(int* );和二維陣列的大小不一樣。
看個例子
int a[6]=;
int b[6]=;
int*c[6];
c[0] = a;
c[1] = b;
除錯結果如下:
c是乙個陣列,有六個元素。第乙個和第二個元素賦值,後面四個沒有賦值。並且c[0],c[1]並沒有指向乙個陣列位址,獲得陣列的所有元素,而是指向了陣列的第乙個元素。即**c[0]= a 等價於 c[0] =&a[0].雖然可以使用c[0][1]訪問a[1],但是c的記憶體不是連續的。
int m = 0;
int n = 1;
c[0] = &m;
c[1] = &n;
從這段**可以看出可以通過c[i][j]訪問二維陣列,是通過位址計算得到的,每個c[i]的值是陣列的首位址,而不是整個個陣列。
sizeof(c[i]) = sizeof(int *)。乙個指標的位址大小
陣列指標
陣列指標的記憶體分配情況和二維陣列一樣,連續分配位址控制項。通常用於二維陣列在不知道有多少行的情況下的動態二維陣列。
int (*p)[6] = new int [n][6]
int (*p)[6]:陣列指標,該陣列需要有乙個特點:必須有6列。p賦值後p[i]的值都確定了。p[i]=p[0]+i*n*sizeof(int)
int (*d)[6] = h;
可以看出d[i]之間的關係為d[i] = d[0]+i*6*sizeof(int )
p是乙個指標所有sizeof(p)= sizeof(int * );sizeof(p[i]) = sizeof(int )*n;
陣列指標通常用於二維陣列的的引數傳遞。
可以把指標陣列強制轉換為陣列指標,陣列指標不能強制轉換為指標陣列。
d = (int(*)[6])c;//強制轉換為陣列指標
這樣就是把c看出了乙個有留個元素的一維陣列,知識這個陣列的值時位址,但是強制轉換後c[0]的位址值,並看成了整數。其中0x0012fee8 = 1244904。就像int testp = (int)p一樣。
這樣的結果是
int **p是乙個二重指標。也可以使用p[i][j]的形式來訪問二維陣列。尤其是在不知道二維陣列的行和列的情況下使用動態的二維陣列
int **i = new int *[3];
for(int index =0;index<3;index++)
i[index]=new int[6];
可以看出這實際上指向的是二維陣列的第乙個元素的位址的位址。類似於動態一維陣列
int *f = newint[6];
f=a;
所以sizeof(i) = sizeof(int **),sizeof(i[index]) = sizeof(int *),並且在堆上的記憶體分配不似二維陣列的分配。更類似於指標陣列的分配。
指標陣列可以直接賦值給二重指標。從動態二維陣列可以看出,二者本質差不多。
陣列指標可以強制轉換為二重指標,但是轉換後結果是這樣的:
i =(int **)d;
i= (int **)h
不能以i[m][n]的形式訪問,這樣的話就意味著二維陣列的引數傳遞不能傳給二重指標。這個原因是什麼呢?看下面這三條語句:
i = (int **)d[0];
i = (int **)&d[0][0];
i = (int **)*d;
這三條語句實際上是一樣的。因為d[0]=&d[0][0]=*d;
這三條產生上述的結果是可以理解的上面說過,int *可以強制轉換為int,同樣int 也可以強制轉換為int*;這樣強制轉換過之後就將d[0][0]的值強制轉換成了位址,所以i[0]的值就是的d[0][0]的值了。但是這三條語句為什麼和i =(int **)d;是一樣的呢?我們知道一維陣列a,至少有兩種含義,1是陣列的首位址,2是陣列第乙個元素的位址。這個時候d的值和的d[0]的值是一樣的,代表的是陣列第乙個元素的位址。所以強制賦值之後不能使用i[m][n]去訪問d陣列了。可以看到i+1實際上及時d[1]的值了。
使用i+1,i等符號是,必須知道i的型別,根據型別移動適當的位元組。舉個例子
void *x=malloc(4);
int *xx = (int*)malloc(4);
當不指明型別是,x+1,x[0],是沒有意義的。不知道要加多少個位址。所以在指標陣列中,c+1=c+sizeof(int *), d+1=d+sizeof(int)*n;
指標傳遞問題小結
include include include void fun char p intmain void 執行結果中並未輸出字串hello其實這裡主函式呼叫fun函式,形參向實參傳遞引數的時候,發生的是拷貝。在fun函式中對區域性指標變數p的任何修改都不會影響到主函式中的指標變數p。值傳遞,形參的修...
c語言指標問題小結
最近使用指標的時候遇到了一些問題,在這裡做乙個簡單的總結,加深下對指標的認識。陣列和指標大部分情況下可以互換使用,但是有些時候卻是必須得區別對待,否則一不小心就會出錯。比如下面四個test例子,test1是對的,test2是錯的,指標指向乙個位址的情況,因為getuartdata 返回乙個指標位址,...
void 指標小結
今天在看memcpy函式原型的時候遇到void指標,我有些地方不明白,就從網上蒐集了一些資料,然後總結一下。先來看下memcpy函式的原型 void memcpy void destination,const void source,size t num 我開始以為void指標可以進行應用和計算,出...