在C語言中,數組名就是一個指針常量,保存數組的首地址。因為數組名是一個常量指針常量,不能修改其指向的值,因此可以定義一個指針變量指向數組。這樣使用數組名加下標可訪問數組中的元素,使用指針名加下標也可訪問數組中的元素。這些在本章前面已經介紹過了。
現在如果再定義一個二級指針變量,讓其指向一級指針,就可使用二級指針變量操作數組。例如,使用以下語句定義二級指針變量:
- int a[10];
- int *p=a;
- int **pp=&p;
這樣,二級指針變量pp、一級指針變量p和數組a之間的關系,如圖9-47所示。
![]() |
(點擊查看大圖)圖9-47 用二級指針操作一維數組 |
1.用二級指針操作一維數組
可使用以下代碼輸出數組a中各元素的值:
【程序9-24】
- #include <stdio.h> //頭文件
- #include <stdlib.h>
- int main()
- {
- int i,a[10]={1,2,3,4,5,6,7,8,9,10};//聲明並初始化
- int *p,**pp;
- printf("使用數組方式輸出數組各元素的值:\n");
- for(i=0;i<10;i++) //使用數組方式輸出
- {
- printf("%4d ",a[i]);
- }
- printf("\n使用一級指針變量輸出數組各元素的值:\n");
- p=a;
- for(i=0;i<10;i++) //使用一級指針變量輸出
- {
- printf("%4d ",*p++);
- }
- printf("\n使用二級指針變量輸出數組各元素的值:\n");
- p=a;
- pp=&p;
- for(i=0;i<10;i++) //用二級指針變量輸出
- {
- printf("%4d ",*(*pp+i));
- }
- printf("\n使用二級指針變量**p方式輸出數組各元素的值:\n");
- p=a;
- for(i=0;i<10;i++,p++)//使用二級指針變量**p方式輸出
- {
- printf("%4d ",**pp);
- }
- printf("\n");
- system("pause");
- return 0;
- }
在以上程序中,分別采用了如下幾種方法輸出數組各元素的值。
使用數組下標方式輸出各元素的值。
使用一級指針變量輸出指向元素的值,然后執行p++使指針指向下一個元素,循環處理將所有數組元素都輸出。
使用二級指針變量的方式輸出數組元素值,在第23行中,首先使用*pp得到一級指針變量p中保存的值,再將其加上一個整數i,再使用運算符*得到具體的值。
使用**pp方式輸出具體元素的值,這時,因為二級指針變量pp指向一級指針變量p,所以只需要改變一級指針變量p所指向的位置,**pp就可以得到不同元素的值。
編譯執行這段程序,得到如下結果,如圖9-48所示。
![]() |
圖9-48 執行結果 |
從以上程序可以看出,對於一維數組,使用一級指針變量可方便地操作數組元素,而使用二級指針變量只會讓情況更復雜。
2.用二級指針操作二維數組
用二級指針操作二維數組的示意圖,如圖9-49所示。同樣在二級指針變量pp中保存一級指針的地址,修改一級指針p的指向,使用**pp就可訪問到不同的數組元素,如圖9-49所示。因為一級指針變量定義為int型,所以對指針變量p進行自增時,將移動到下一個int變量(即一個數組元素),如圖9-49右圖所示。
![]() |
(點擊查看大圖)圖9-49 用二級指針操作二維數組示意圖 |
下面編寫程序,用二級指針變量輸出二維數組的數據。
【程序9-25】
- #include <stdio.h>//頭文件
- #include <stdlib.h>
- int main()
- {
- int i,j,a[3][4]={{1,2,3,4},{5,6,7,8},
{9,10,11,12}}; //聲明並初始化 - int *p,**pp;
- printf("用二級指針方式輸出二維數組:\n");
- pp=&p;
- for(i=0;i<3;i++)//用二級指針方式輸出
- {
- p=a[i];
- for(j=0;j<4;j++)
- printf("%4d",*(*pp+j));
- printf("\n");
- }
- printf("用二級指針**pp輸出二維數組:\n");
- for(i=0;i<3;i++)//用二級指針**pp輸出
- {
- p=a[i];
- for(j=0;j<4;j++,p++)
- printf("%4d",**pp);
- printf("\n");
- }
- printf("\n"); //輸出換行
- system("pause");
- return 0;
- }
在該程序中,首先使二級指針變量pp指向一級指針變量p,因為p的內存地址不會再變化,所以可將該語句放在程序前面,在后面的循環中不需要修改其值。然后,使用*(*pp+j)的方式輸出數組中的值,這種方式在本章前面曾多次使用,首先通過*pp得到一級指針變量p保存的值(從語句p=a[i]可知道,變量p中保存着二維數組某行的首地址),再將其加上一個整數j,得到該行第j個元素的地址,最后使用運算符*得到該地址的值。
在第二種方法中,使用**pp方式輸出二維數組元素的值,該表達式可看做為*(*pp),*pp得到變量p中的值,從語句p=a[i]可知道,變量p中保存着二維數組某行的首地址,該首地址也是該行第1個元素的地址,因此使用*(*pp)將輸出某行第1個元素的值。接着執行循環中的p++,使一級指針變量的值增加1,因該變量保存的值是一個指針,所以對其進行自增運算將指向下一個元素,即該行的第2個元素,再使用**pp即可輸出第2個元素的值。通過內循環語句,即可將二維數組一行中的每個元素輸出。再通過外循環,即可輸出整個二維數組中的元素值。
編譯執行這段程序,得到如下結果,如圖9-50所示。
![]() |
圖9-50 執行結果 |
3.用二級指針操作指針數組
在本章的程序9-22中,使用指針數組操作多個字符串。還可以通過二級指針變量的方式進行這種操作,其示意圖如圖9-51所示。首先定義一個字符串指針數組s,用來指向多個字符串常量,再定義一個二級指針變量p,使其指向數組s,因數組s中的每個元素都是數組,因此指針變量p必須定義為指向指針的指針(即二級指針)。
![]() |
(點擊查看大圖)圖9-51 二級指針與數組 |
修改程序9-22中的strsort()函數,使其形參使用二級指針的方式。
【程序9-26】
- #include <stdio.h> //頭文件
- #include <stdlib.h>
- #include <string.h>
- void strsort(char **p,int n); //函數聲明
- int main()
- {
- int i;
- char *s[]={ //初始化
- "C",
- "Basic",
- "Foxpro",
- "Visual Studio"
- };
- strsort(s,sizeof(s)/4); //排序
- printf("\n排序后的數據:\n");
- for(i=0;i<sizeof(s)/4;i++) //輸出
- {
- printf("%s\n",s[i]);
- }
- system("pause");
- return 0;
- }
- void strsort(char**p,int n) //自定義函數
- {
- int i,j;
- char *pstr;
- for(i=0;i<n-1;i++)
- {
- for (j=i+1;j<n;j++)
- {
- if (strcmp(*(p+i),*(p+j))>0)//比較
- {
- pstr=*(p+j);
- *(p+j)=*(p+i);
- *(p+i)=pstr;
- }
- }
- }
- }
編譯執行這段程序,得到如下結果,如圖9-52所示。
![]() |
圖9-52 執行結果 |
在該程序中,重新編寫自定義函數strsort()。在函數頭的形參中,使用二級指針變量p接收一個指針變量的地址作為參數(指針數組的每一個元素是一個指針,指針數組名就是一個指向指針變量的指針),變量n為需要處理的字符串數量。
在自定義函數strsort()中,定義了一個字符指針變量pstr,作為臨時指針變量,用來保存需要交換的指針地址。
對照前面的示意圖,*(p+i)表示p[i],即與數組s[i]相同,得到其指向的字符串常量。程序中調用庫函數strcmp()比較兩個字符串的大小,再根據需要交換指針。