今天遇到乙個問題,要開闢乙個二維指標空間,詳細的看了一下網上有關動態指標、動態陣列等開闢方法以及學習前輩們對於動態陣列問題的解決經驗!
一、 首先說明一下多重指標問題,這裡解釋到第三層,為了方便理解,我們可以將三重指標理解為三維陣列,
首先看乙個經典的例子:
int ***a,x=10,y=20;
a=(int ***)malloc(sizeof(int)*x);//分配是什麼?
for(i=1;i<10;i++)
for(i=1;i
1:
*a=(int **)malloc(sizeof(int)*x);可以理解為二重指標的第一層,分配了10個int型的二重指標空間
a是三重指標的位址,*a是二重指標的首位址;(*a)[0];(*a)[1];(*a)[2];(*a)[3];(*a)[4]........
2: (*a)[i]=(int *)malloc(sizeof(int)*y);這個代表每乙個二層指標又被分配了空間;這裡每一二層指標被分配了
20個(int *)的指標;即,每一二層指標又有20個孩子
3: (*a)[i][j]=10;這樣賦值正確,前邊的(*a)是獲取乙個二維陣列,後邊是乙個二維陣列的乙個元素。直接賦值是可以的
4: 我們同樣可以理解為樹形,幾重指標就是幾層樹
以上是關於三維指標的解釋,二維指標也就是可以理解成二維陣列。
二、陣列的指標、指標陣列以及指向指標的指標
考慮陣列的指標的時候我們要同時考慮型別和維數這兩個屬性。換一句話,就是說乙個陣列排除在其中儲存的數值,那麼可以用型別和維數來位置表示他的種類。
a)一維陣列
在c和c++中陣列的指標就是陣列的起始位址(也就第乙個元素的位址),而且標準文件規定陣列名代表陣列的位址(這是位址數值層面的陣列表示)。例如:
int a[10]; int *p;
p=&a[0]//和p=a是等價的:
因為a是陣列名,所以他是該陣列的位址,同時因為第乙個元素為a[0],那麼&a[0]也代表了該陣列的位址。但是我們是不是就說乙個陣列名和該陣列的第乙個元素的&運算是一回事呢?在一維的時候當時是的,但是在高維的時候,我們要考慮到維數給陣列帶來的影響。
a[10]是乙個陣列,a是陣列名,它是乙個包含10個int型別的陣列型別,不是一般的指標變數噢!(雖然標準文件規定在c++中從int到int*直接轉換是可以的,在使用的時候似乎在函式的引數為指標的時候,我們將該陣列名賦值沒有任何異樣),a代表陣列的首位址,在數字層面和a[10]的位址一樣。這樣我們就可以使用指標變數以及a來操作這個陣列了。
所以我們要注意以下問題:
(1) p[i]和a[i]都是代表該陣列的第i+1個元素;
(2) p+i和a+i代表了第i+1個元素的位址,所以我們也可以使用 *(p+i)和*(a+i)來引用物件元素;
(3)p+1不是對於指標數量上加一,而是表示從當前的位置跳過當前指標指向型別長度的空間,對於win32的int為4byte;
b)多維陣列
對於二維陣列a[4][6];由於陣列名代表陣列的起始位址,所以a(第一層)和第乙個元素a[0][0]位址的數字是相同的,但是意義卻是不同的。對於該陣列我們可以理解為:a的一維陣列(第一層),它有四個元素a[0]、a[1]、a[2]、a[3](第二層),而每個元素又含有6個元素a[0][0],a[0][1],a[0][2],a[0][3],a[0][4],a[0][5](第三層),…到此我們終於訪問到了每個元素了,這個過程我們經歷了:a->a[0]->a[0][0];
整體來講:a是乙個4行5列的二維陣列,a表示它指向的陣列的首位址(第乙個元素位址&a[0]),同時a[0]指向一行,它是這個行的名字(和該行的第乙個元素的首位址相同(第乙個元素為位址&a[0][0]))。所以從數字角度說:a、a[0]、&a[0][0]是相同的,但是他們所處的層次是不同的。
既然a代表二維陣列,那麼a+i就表示它的第i+1個元素*(a+i)的位址,而在二維陣列中
*(a+i)又指向乙個陣列,*(a+i)+j表示這個陣列的第j+1個元素的位址,所以要訪問這個元素可以使用 *(*(a+i)+j)(也就是a[i][j])。
他們的示意圖為(虛線代表不是實際存在的):
對照這個圖,如下的一些說法都是正確的(對於a[4][6]):
a是乙個陣列型別,*a指向乙個陣列;a+i指向乙個陣列;a、*a和&a[0][0]數值相同;a[i]+j和*(a+i)+j是同乙個概念; 總結一下就是:我們對於二維指標a,他指向陣列a[0,1,2,3],使用*,可以使他降級到第二層次,這樣*a就指向了第乙個真正的陣列。對於其他的情況我們也可以採用相同的方式,對於其他維數和型別的陣列我們可以採用相類似的思想。
說到指向陣列的指標,我們還可以宣告乙個指標變數讓它指向乙個陣列。例如:
int (*p)[5];
這時p就是乙個指標,要指向乙個含有5個int型別元素的陣列,指向其他的就會出現問題。
這個時候我們可以使用上面的什麼東西來初始化呢?
我們可以使用*a,*(a+1),a[2]等。
原因很簡單:我們在乙個二維的陣列中,那麼表達方式有上面的相互類似的意義呢?只有 *a,*(a+1),a[2]等,
c)指標陣列
乙個指標陣列是指乙個陣列中的每個元素都是乙個指標,例如:
int *p[10];//而不能是int (*p)[10]
或者char *p[10];
此時p是乙個指標(數值上和&p[0]一樣);
在前面有int t[10];
int * pt=t;//使用pt指向t
那麼這裡我們用什麼指向int *t[10]中的t呢?我們要使用乙個指標的指標:
int **pt=t;
這是因為:在int *t[10]中,每個元素是指標,那麼同時t又指向這個陣列,陣列上和&t[0]相同,也就是指向t[0],指向乙個指標變數,可以說是乙個指標的指標了,所以自然要用
int **pt;
d)指標的指標
乙個指標變數內部可以儲存乙個值,這個值是另外乙個物件的位址,所以我們說乙個指標變數可以指向乙個普通變數,同樣這個指標變數也有乙個位址,也就是說有乙個東西可以指向這個指標變數,然後再通過這個指標變數指向這個物件。那麼如何來指向這個指標變數呢?由於指標變數本身已經是乙個指標了(右值),那麼我們這裡就不能用一般的指標了,需要在指標上體現出來這些特點,我們需要定義指標的指標(二重指標)。
int *p1=&i; int**p2=&p1;
綜合以上的所有點,下面是我們常常看到一些匹配(也是經常出錯的地方):
int a[3],b[2][3],c,*d[3]; void fun1(int *p); void fun2(int (*p)[3]); void fun3(int **p); void fun4(int p[3]); void fun5(int p); void fun6(int p[2][3]); void fun7(int (&p)[3]);
函式 不會產生編譯時刻的可能值(但邏輯上不一定都對)函式
不會產生編譯時刻的可能值(但邏輯上不一定都對)
fun1
a, &a[i], *b ,b[i],&b[i][j] ,&c ,d[i]
fun2 b
,b+i,
fun3 d
fun4
a, &a[i], *b ,b[i],&b[i][j] ,&c ,d[i]
fun5
a, &a[i], *b ,b[i],&b[i][j] ,&c ,d[i]
fun6 b
fun7 a
三、對於動態陣列問題:
參閱他人的建議得知:使用一維陣列實現多為陣列的功能。定義動態啊的一維陣列比較簡單,而且所派分的記憶體單元都是連續的,其實在記憶體中的儲存都是在一塊連續的記憶體塊上儲存,性質一樣!所以建議使用一維陣列實現多維的功能;
例項如下:
1、用一重指標
int i,j,num1,num2;
int *p=new int[num1*num2];
for(i=0;i
2、用二重指標
int num1,num2;
int **p;
p=new int*[num1];//開闢空間,理解起來有點難
for(int i=0;i
另外兩個例項:
一維動態陣列的例項:
#include
using namespace std;
int main()
cout<
for(int i=1;i<=n;i++)
delete arr;//動態空間釋放}
複製**
二維動態陣列的例項:
#include
using namespace std;
int main()
cout<<"*****************下面是輸入部分*****************"<
for(int i=0;i
}cout<<"*****************下面是輸出部分*****************"<
for(int i=0;i
}for(int i=0;i
delete arr[i];
delete arr;
arr=null;}
C 多重繼承的指標問題
下面說說c 多重繼承中關於指標的一些問題。指標指向問題 先看下面的程式 class base1 class base2 class derive public base1,public base2 virtual void fun2 int main 我電腦上的執行結果 首先,可以看到 od和pb1...
C 多重指標
首先看乙個經典的例子 int a,x 10,y 20 a int malloc sizeof int x 分配是什麼?for i 1 i 10 i for i 1 i 1 a int malloc sizeof int x 可以理解為二重指標的第一層,分配了10個int型的二重指標空間 a是三重指標...
C 指標與動態陣列
使用new 和 delete,動態地調整陣列大小,通常是當前陣列滿了的時候,將陣列容量翻倍,假設用int變數capacity代表當前陣列大小,ptr是當前陣列指標 float tempptr new float capacity 2 for int i 0 i capacity i delete p...