我正在尝试将二维数组传递给函数。我尝试了互联网上提供的不同解决方案。
int arr[3][4];
fun (arr);
1) void fun(int *a[4]) {} -- result into a compilation error (cannot convert int (*)[4] to int **)
2) void fun(int(*a)[4]) {} -- works fine.
我想知道上述两个声明有什么区别,以及 1. 案例中有什么错误。
我正在尝试将二维数组传递给函数。我尝试了互联网上提供的不同解决方案。
int arr[3][4];
fun (arr);
1) void fun(int *a[4]) {} -- result into a compilation error (cannot convert int (*)[4] to int **)
2) void fun(int(*a)[4]) {} -- works fine.
我想知道上述两个声明有什么区别,以及 1. 案例中有什么错误。
好吧,这就是永远有用的cdecl所说的:
int *a[4]
表示“将 a 声明为指向 int 的指针的数组 4”int(*a)[4]
表示“将 a 声明为指向 int 数组 4 的指针”这声明了一个包含 4 个指向整数的指针的数组:
int* a[4]; // (a)
另一方面,这:
int (*a)[4]; // (b)
声明一个指向 4 个整数数组的指针。
由于数组在用作函数参数时衰减为指针(指向它们的第一个元素),因此将类型对象传递int arr[3][4]
给接受上述类型(b)参数的函数将成功(衰减为指向 的指针int[4]
,即 an int (*)[4])
,而它将当参数类型为(a)时失败。
除非它是、 或 一元运算符的操作数sizeof
,或者是用于在声明中初始化另一个数组的字符串文字,否则“N-element array of ”类型的表达式将转换为“pointer”类型的表达式到",表达式的值将是数组中第一个元素的地址。_Alignof
&
T
T
在函数调用中
fun(arr);
表达式 的类型arr
是“4 元素数组的 3 元素数组int
”。由于arr
不是sizeof
, _Alignof
, 或一元运算符的操作数&
,它将被转换为“指向 4 元素数组的指针”类型的表达式,int
写为int (*arr)[4]
,其值将是 的地址a[0]
。
后缀运算符 like[]
和()
比一元运算符 like 具有更高的优先级*
,因此*a[N]
是N
-element 指针数组,而(*a)[N]
是指向-element 数组的指针N
。同样,*f()
是一个函数返回一个指针,(*f)()
而是一个指向函数的指针。
int* a[4]
是一个 4 int*
s的数组int (*a)[4]
int
是一个指向 4 s数组的指针数组的名称可以转换为指向其第一个元素的指针。也就是说arr
,由于它是 an 的名称int[3][4]
,将转换为指向其第一个元素的指针,该元素arr
本身就是 an int[4]
。该类型是int(*)[4]
. 这就是为什么你可以arr
在第二种情况下通过。
在 C++ 中,您可以像这样传递对完整数组的引用:
void fun(int(&a)[3][4]) {}
在这种情况下,不会发生数组到指针的转换。您只是在引用 2D 数组本身。
int *a[4]
是一个由 4 个指针组成的数组int
,而int(*a)[4]
是一个指向 4 个数组的指针int
。
由于数组衰减为指向其第一个元素的指针(只要它不用作&
,sizeof
或的操作数_Alignof
),a[3][4]
将被转换为(*a)[4]
.