第42题  设有下面程序

c_choice42-01

则程序的运行结果是­

­      A    16

­      B    12

­      C    17

­      D    23

答案  B

解析    考查用指针式访问二维数组。

变量声明

­        int   a[3][4] = {2, 4, 6, 8, 10, 12, 1, 3, 5, 7, 9, 11};
­        int   (∗p)[4] = a;

定义3行4列整型数组a,定义指向长度为4的整型数组的指针p,效果如下图所示:

c_choice42-03

应理解为:a是一维数组,含3个元素(红框表示),这3个元素又都是长度为4的一维整型数组,因此二维数组是以一维数组为元素的一维数组,共12个整数,连续存储。

标识符a有两个意义:左边红色a强调它是数组变量名,下方红色a强调它又是指针,且固定指向首元素,即首个长度为4的一维数组。C语言规定,数组名是指向首元素的常量指针,不能被赋值,即不能改变指向。

声明

­        int   (∗p)[4] = a; ­

定义指向长度为4的整型数组的指针p,并将常量指针a的值赋于p,因此p初始指向数组a的首元素,如上图所示,但指针p与a不同,根据需要,可再被赋值、改变指向。

顺便解释语法形式(∗p)[4]的意义,设有声明

­        int   x[4] = {1,2,3,4};

把x定义为长度为4的整型数组的名字,而∗是间接引用操作符,∗p是对指针p的间接引用,即∗p是指针p所指对象的名字,可见∗p与x的语法地位相当,即∗p是长度为4的整型数组名,p自然就是指向长度为4的整型数组的指针,达成指针声明和引用一致。因为∗的优先级低于[ ],所以圆括号是必须的。如果写成

­        int   ∗p[4];

那么,这是定义p为长度为4的数组,其元素类型为整型指针,语义完全不同。

C语言还规定,数组元素只能通过指针访问。因为指针a指向首元素(一维数组),那么a[0]、a[1]、a[2]就分别是3个构成二维数组a的长度为4的一维数组的名字,既然a[0]、a[1]、a[2]都是一维数组名,所以它们分别是指向各自首元素的整型指针,见上图上方黑色a[0]、a[1]、a[2]所标识,再进一步,一维数组a[0]的4个整型元素的名字分别是a[0][0]、a[0][1]、a[0][2]、a[0][3],a[1]和a[2]的4个元素名可同理写出,如上图所示。

对于任何一维数组x,下标式x[i]等价于指针式∗(x+i)。对于任何二维数组y,下标式y[i][j]等价于∗(∗(y+i)+j)。下标式由编译器转换为指针式再行翻译。根据以上陈述可知,本题程序等价于下面程序:

c_choice42-05

只把其中的指针式∗(∗(p+k)+l)改成了p[k][l],其余均不变。

由于二维数组通常用于表示矩阵、行列式等数值的行列结构,因此二维数组a可理解为如下直观结构:

c_choice42-04

切记其中a[i][j]等价于∗(∗(a+i)+j),也等价于∗(∗(p+i)+j)。

程序中的语句

­      l = sum = 0;
­      for (k = 0; k < 2; k++)
­            sum += ∗(∗(p+k)+l);
­      printf(″%d\n″, sum);

l = sum = 0;将l和sum同时清0为for循环做好准备,在for循环过程中,k依次取0和1,而l保持0不变,把p[k][l]的各种可能取值,即p[0][0]和p[1][0]、即a[0][0]和a[1][0]的值累加于sum中,得到2+10 = 12。

知识点

① 三行四列的二维整型数组a的直观图解如下:

c_choice42-04

a[i][j]等价于∗(∗(a+i)+j),因为int  (∗p)[4] = a; 定义指向长度为4的整型数组的指针p,并将常量指针a的值赋于p,所以a[i][j]也等价于p[i][j],进而等价于∗(∗(p+i)+j)。

练习题1  设有下面程序

c_choice42-02

则程序的运行结果是­

­      A    7

­      B    16

­      C    23

­      D    17

答案  A

解析  在for循环过程中,i依次取0和1,而j保持2不变,把p[i][j]的各种可能取值,即p[0][2]和p[1][2]、即a[0][2]和a[1][2]累加于s中,得到6+1 = 7。

赞赏

返回