二级指针与二维数组
7.9 指向指针的指针 1. 指向指针的指针的定义、赋值及引用 如果一个指针变量存放的是另一个指针变量的地址,则称这个指针变量为指向指针的指针变量,简称为“二级指针”变量,其定义的一般格式如下: 基类型名 **(指针变量名); 例如: int i=10; int *p=&i; int **pp=&p;
下列程序段的输出结果是( ) int **pp,*p,a=10,b=20; pp=&p; p=&a; p=&b; printf("%d,%d\n",*p, **pp); A) 10,20 B) 20,10 C) 20,20 D)10,10
7.7 指向二维数组的指针 7.7.1 二维数组的地址 C语言中,二维数组可以看成由多个一维数组组成。 例如:int a[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}}; 可以按下面的方式来看待数组a: 二维数组a可以看成是由a[0]、a[1]、a[2]三个元素组成的一维数组,a是它的数组名。a[0]、a[1]和a[2]又都是一维数组,它们的数组名分别叫a[0]、a[1]和a[2] 。 由于数组名是指针,所以a[0]、a[1]和a[2] 为一级指针,它们的基类型是int。a是是由三个一级指针组成的数组。 a与a[0]的区别?a+1与a[0]+1区别?
a+1跨过了二维数组的一行,所以,a、a+1和a+2称为行地址。 相对于a[0]而言,a[0]+1只跨过了二维数组的一个元素,所以将a[0]、a[0]+1、a[0]+2等称为列地址。
通过以上分析可以看出: (1) a+i是第i行的地址,所以,*(a+i)即为a[i]。这样,a[i][j] 等价于 (*(a+i))[j]。 (2) a[i]+j是第i行第j列元素的地址,所以,*(a[i]+j)等价于a[i][j]。将a[i]用*(a+i)替换得:*(*(a+i)+j)也等价于a[i][j]。 上述等价关系总结如下: a[i][j] ←→ (*(a+i))[j] ←→ *(a[i]+j) ←→ *(*(a+i)+j)
用二级指针访问二级数组 #include <stdio.h> #define N 2 #define M 3 int main (void ) { static int a[N][M]={1,2,3,4,5,6}; int *arr[N]={a[0],a[1]}; int i,j,**p=arr; for (i=0;i<M;i++) printf ("%d ",*(*p+i)); printf("\n"); for(j=0;j<N;j++) for (i=0;i<M;i++) printf ("%d ",*(*(p+j)+i)); printf("\n"); return 0; } 运行结果如下: 1 2 3 1 2 3 4 5 6
二维数组a 1 2 3 4 5 6 a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2] 指针数组arr a[0] a[1] p p+1 arr[0] arr[1] 二级指针变量p *p *(p+1) *p+1 *(p+1)+1 *(p+1)+2
7.7.2 指向二维数组行的指针变量 也就是定义指向二维数组行的指针变量。 例如,对二维数组a[3][4],可用如下格式定义指向行的指针变量: int (*p)[4]; 其中,[4]表示二维数组列的大小 对行指针进行赋值时只能赋行地址。例如: int a[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}}; p=a; 或 p=&a[0]; 不能赋列地址,如下面的赋值语句是错误的: p=a[0]; 或 p=&a[0][0];
若有定义语句int (*p)[4];,则以下说法正确的是( ) A) 定义语句非法 B) p是一个指针数组,每个元素是一个指向整型变量的指针变量 C) p是一个行指针变量,可以将每行具有四个整型元素的二维数组名赋给它 D) p是一个指向整型变量的指针变量
设有程序段: int a[2][3],(*pa)[3],x; pa=a; 则以下对数组元素的引用,错误的是( ) A) x=*(a[0]+2); B) x=*pa[2]; C) x=pa[0][0]; D) x=*(pa[1]+2);
7.6 指针数组 一维指针数组的定义格式如下: 基类型 *指针变量名[数组长度]; 例如: 基类型 *指针变量名[数组长度]; 例如: int *p[3], i=1, j=2, k=3; p[0] = &i; p[1] = &j; p[2] = &k; printf("%d,%d,%d\n",*p[0],*p[1],*p[2]); 数组元素是指针
若有定义语句: char *name[]={"JAME","XML","C++"};,则语句printf("%s\n",name[2]);的输出结果是( ) A) JAME B) XML C) C++ D) 不定值
【例7-14】对参加北京奥运会的国家名称按由小到大的顺序排序后输出。 采用两种方法来实现,并比较它们的优劣,以便体会到采用指针的好处。 数组法与指针法
#include <stdio.h> #include <string.h> #define N 4 #define LEN 20 void main() { int i,j; char temp[LEN],name[N][LEN]={“China”,”America”,”Australia”,”Japan”}; for(i=1;i<=N;i++) //排序,控制趟数 for(j=0;j<N-i;j++) //控制每一趟的比较次数 if(strcmp(name[j],name[j+1])>0 { strcpy(temp,name[j]); strcpy(name[j],name[j+1]); strcpy(name[j+1],temp); } for(i=0;i<N;i++) printf("%s\n",name[i]);
#include <stdio.h> #include <string.h> #define N 4 void main() { int i,j; char *temp,*name[N]={"China","America","Australia","Japan"}; for(i=1;i<=N;i++) //排序,控制趟数 for(j=0;j<N-i;j++) //控制每一趟的比较次数 if(strcmp(name[j],name[j+1])>0 { temp=name[j]; name[j]=name[j+1]; name[j+1]=temp; } for(i=0;i<N;i++) printf("%s\n",name[i]); 移动指针