C

C程序实例7-多维(二维)数组名是什么指针?

which pointer of the name of multidimensional arrays

Posted by xuepro on October 30, 2017

对于一维数组,数组名就是存储空间的首地址,即第一个元素的地址,比如下面的程序:

#include <strdio.h>

int main(){
  int a[6],i;
  int *p = a;   /* a就是数组的起始地址,即第一个元素的地势:&a[0] */
  for(i = 0 ; i<6;i++)
     scanf("%d",&a[i]); 
     /*等价于
       scanf("%d",a+i); 
       scanf("%d",p+i); 
     */  

  /*  *(a+i)等价于a[i]  */
  for(i = 0 ; i<6;i++){
     printf("%d",*p++);   
     /*等价于
       printf("%d",*(a+i)); 
       printf("%d",*(p+i)); 
     */ 
  }  
}

假设定义二维数组a[3][4]如下:

int a[3][4]={ {0,1,2,3}, 
              {4,5,6,7},
              {8,9,10,11}
           };

那么数组名a是什么呢?是a[0][0]的地址“&a[0][0]”吗?

答案:不是

那么二维数组名到底是一个什么样的指针呢?

C语言的二维数组可以看成数据元素是一维数组的一维数组,因此,a代表整个二维数组的首地址,也是二维数组(下标为0的)第1行的首地址。

即a是a[0]的地址,即&a[0]。而a[0]本身又是一个“含4个元素的一维数组”,因此a[0]是a[0]这个数组的起始地址,即其第一个元素的地址,即a[0]就是&a[0][0]。因此可以用一个int *指针来访问a[0]:

   int *p = a[0];
   for(int i = 0 ; i<4;i++)
      printf("%d",*p++);  /*先输出*p,再p++ */
  
   /*或*/
   int *p = a[0];
   for(int i = 0 ; i<4;i++)
      printf("%d",p[i]);

那么,自然得,会想a应该是一维数组{a[0],a[1],a[3]}的起始地址,既然a[i]的类型是int *,那么a的类型自然应该是 (int *)*即int **类型了?

于是,你可能这样写:

 int **q = a;  

编译器遇到下列语句会报错:

[-Wincompatible-pointer-types]
     q = a;
       ^

Why? (为什么?) 你会大叫!

看一下这张图:

a是第1行(即a[0])的指针,那么a+1就是第2行(即a[1])的指针,a+2就是第3行(即a[2])的指针,…

a确实是一个“一维数组”,但其中的元素是“含4个元素的一维数组”而不是“int *”类型的元素。

我们知道不管是什么类型的指针int *、int **、double *,通常占据4个字节,但“含4个元素的一维整型数组”本身就是一种类型啊,它占据的是4*4个字节(假如一个整数占4个字节的话)。

因此,a是数据元素是“含4个元素的一维整型数组”的一维数组。 那么a作为这个数组的首地址,其类型应该

  4个元素的一维整型数组 *

因此,可以如下写:

  4个元素的一维整型数组 *q = a; 

当然这是伪代码,真正的C代码应该写成:

 int (*q) [4] = a;

那么为什么不写成:

 int[4] *q = a;

这你们要去问C语言的设计者了!

示例:

#define  _CRT_SECURE_NO_WARNINGS   /* for VS*/

#include <stdio.h>

#include <stdlib.h>

#define M 3

#define N 4

int main(){
  int *p;
  int(*q)[N];
  int a[M][N];
  int i, j;
  p = *a;
  for (i = 0; i<M; i++)
    for (j = 0; j<N; j++)
      scanf("%d", &a[i][j]);

  printf("first output\n");
  p = *a;
  for (i = 0; i<M; i++){
    for (j = 0; j<N; j++)
      printf(" %d", *p++);
    printf("\n");
  }

  printf("second output\n");
  q = a;
  for (i = 0; i<M; i++, q++){
    /* q是a[i]的指针*/
    p = *q; /* p就是a[i]本身,4个整数构成的一维数组*/
    for (j = 0; j<N; j++)
      printf(" %d", *p++);
    printf("\n");
  }

  return 0;
}

支付宝打赏 微信打赏

您的打赏是对我最大的鼓励!