指向数组和2D数组表示的指针

时间:2011-12-31 15:59:09

标签: c arrays pointers

我对指向数组和2D数组

的语法有疑问
#include<stdio.h>
#include<stdlib.h>

void show ( int q[][4], int row )
{
  int i, j ;
  for ( i = 0 ; i < row ; i++ )
  {
     for ( j = 0 ; j < 4 ; j++ )
      printf ( "%d ", q[i][j] ) ;
    printf ( "\n" ) ;
  }
  printf ( "\n" ) ;
}

int main( )
{
 int a[][4] = {
                {1, 2, 3, 4},
                {5, 6, 7, 8},
                {9, 0, 1, 6}
              } ;
 show ( a, 3, 4 ) ;
 return 0;
}

以上代码适用于以下所有符号

void show ( int q[][4], int row )
void show ( int q[3][4], int row )
void show ( int ( *q )[4], int row, int col )

 int q[][4]  == int q[3][4]==int ( *q )[4] // represents pointer to 1D array with size 4

我已经读过这个

int q[ ][4]; 这与int ( *q )[4]相同,其中q是指向数组4的指针 整数。唯一的好处是我们现在可以使用更多 熟悉的表达式q[i][j]来访问数组元素。

问题:

show()函数同时使用这两个函数int q[][4]int q[3][4]来接收2D数组的地址。

但这些是2D阵列的表示吗?

我们不能像以下那样分配2D

  int (*a)[4] = {                 
                {1, 2, 3, 4},
                {5, 6, 7, 8},
                {9, 0, 1, 6}
              } ; 

但可以通过此声明分配2D

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

int (*a)[4]int a[][4]不同,那么如何在show函数中使用“指向数组的指针”和“2D数组表示法”?

3 个答案:

答案 0 :(得分:2)

数组不是指针,但在许多情况下,数组会衰减为指针,例如作为函数参数传递时。因此,当您将int q[][4]传递给函数时,该函数会收到一个int (*q)[4],一个指向四个int数组的指针。这就是为什么两个表格都作为show()的参数。但是对于声明和初始化,真实类型很重要,所以你不能用数组初始化器初始化指针。

答案 1 :(得分:2)

函数有关于数组参数的特殊规则,基本规则是如果你说的是函数的原型,而你的第一个单词是数组,你将它改为“指向”,以便

(int foo[5]) ==> array[5] of int ==> pointer to int
(int foo[][4]) ==> array[] of array[4] of int  ==>  pointer to array[4] of int
(int (*foo)[4]) ==> pointer to array[4] of int ==>  pointer to array[4] of int
(int *argv[]) ==> array of pointer to int ==> pointer to pointer to int

在函数中,不会发生转换,并且数组和指针类型之间存在很大差异。

int a[] = {5, 3, 2};

合法,但

int *a = {5, 3, 2};

不是。通常,您无法从数组初始值设定项分配指针。相反,c99提供复合文字:

int *a = (int[]){5, 3, 2};

int (*a)[4] = (int [][4]){
     {2, 2, 3, 1},
     {2, 3, 5, 3},
};

答案 2 :(得分:0)

首先,来自C标准的一些语言:

6.3.2.1左值,数组和函数指示符
...
3除非它是sizeof运算符或一元&运算符的操作数,或者是用于初始化数组的字符串文字,否则表达式的类型为''数组 type < / em>''被转换为类型为''指向 type '的指针的表达式,它指向数组对象的初始元素,而不是左值。如果数组对象具有寄存器存储类,则行为未定义。

在对show函数的调用中,表达式 a具有类型为“{element = 1}}的4元素数组的3元素数组”。根据上面的规则,在调用之前,此表达式是替换,其表达式为“指向int的4元素数组的指针”;因此,int接收类型为show的指针值,而不是数组。

更多标准语言:

6.7.5.3函数声明符(包括原型)
...
7参数声明为'' type ''的数组应调整为''限定指向 type ''的指针,其中类型限定符(如果有的话)是在数组类型派生的int (*)[4][内指定的那些。如果关键字]也出现在数组类型派生的static[内,那么对于每次调用该函数,相应实际参数的值应提供对第一个的访问权限。数组的元素,其元素至少与size表达式指定的元素一样多。

因此,在函数参数声明的上下文中,]T a[n]T a[]都是等效的。如果T *a是数组类型,例如“T的4个元素数组”,则intint a[3][4]int a[][4]都是等效的。

请注意,对于函数参数声明,这只是 true。当您声明一个数组 object 时,会使用以下语言:

6.7.8初始化
...
22如果初始化未知大小的数组,则其大小由具有显式初始值设定项的最大索引元素确定。在其初始化列表的末尾,该数组不再具有不完整的类型。

所以当你写

int (*a)[4]

您声明的是int a[][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 0, 1, 6} } ; 的Nx4数组,而不是指向int数组的指针 - 内部维度3是从初始化程序中的4个元素数组的数量推断出来的。