我对指向数组和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数组表示法”?
答案 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个元素数组”,则int
,int 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个元素数组的数量推断出来的。