以下是written作为在函数原型中添加用于声明数组类型的花哨的*
星形语法的基本原理 - 仅用于在我们进入问题之前澄清:
函数原型可以具有可变长度的参数 数组类型(第6.7.5.2节)使用特殊语法
int minimum(int,int [*][*]);
这与名称中的其他C原型一致 不需要指定参数。
但是我非常有信心我们只能使用像这样的未指定大小的普通数组(这里重新编写上面给出的名为minimum
的函数示例,我相信它具有相同的效果完全相同的功能(除了使用size_t
代替int
作为第一个参数,但在案例中并不重要)):
#include <stdio.h>
int minimum(size_t, int (*)[]);
int (main)()
{
size_t sz;
scanf("%zu", &sz);
int vla[sz];
for(size_t i = 0; i < sz; ++i)
vla[i] = i;
minimum(sizeof(vla) / sizeof(*vla), &vla);
int a[] = { 5, 4, 3, 2, 1, 0 };
minimum(sizeof(a) / sizeof(*a), &a);
}
int minimum(size_t a, int (*b)[a])
{
for(size_t i = 0; i < sizeof(*b) / sizeof(**b); ++i)
printf("%d ", (*b)[i]);
return printf("\n");
}
因为我很确定标准中有一些地方说明2个阵列只有在它们的大小相等时才兼容,如果它们是可变的则无关紧要。
我的观点也得到证实,minimum
定义不会抱怨“冲突类型”,因为如果它的某些参数具有不兼容的类型(我认为不是这样的话)这两个数组的大小都在编译时未指定 - 我引用了minimum
的第二个参数。
除此之外 - 你能指出一个[*]
的单个用例,使用普通的未指定大小的数组无法替换吗?
上面的代码使用clang和gcc编译时没有任何警告。它还产生预期的输出。
对于不了解C的人(或任何认为他/她知道它的人) - 类型数组的函数参数被隐式转换为“指向其元素类型的指针”。所以这个:
int minimum(int,int [*][*]);
调整为:
int minimum(int,int (*)[*]);
然后我认为它也可以写成:
int minimum(int,int (*)[]);
没有任何后果,并且具有与上述2种形式相同的行为。从而使[*]
形式过时。
答案 0 :(得分:6)
[]
只能用作最左边的&#34;维度说明符&#34;多维数组,而[*]
可以在任何地方使用。
在函数参数声明中,最左边(仅!)[...]
无论如何都会调整为(*)
,因此可以在该位置使用(*)
,但会有一定的清晰度。
可以在下一个最左边的[...]
中省略维度,留下空括号。这将使数组元素类型不完整。这不是什么大问题,因为人们可以在接近使用点(例如在函数定义中)完成它。
下一个[...]
需要一个不能省略的数字或*
。这些声明
int foo (int [*][*][*]);
int foo (int (*)[*][*]);
int foo (int (*)[ ][*]);
都是兼容的,但没有一个与它们兼容,并没有将第三个维度指定为*
或数字。如果第三维确实是变量,*
是唯一的选择。
因此,[*]
至少对于尺寸3及以上是必要的。
答案 1 :(得分:6)
除此之外 - 你能指出一个不能用于[*]的单个用例吗? 使用普通的未指定大小的数组替换?
当您传递三维VLA数组时会出现这种情况:
int minimum(size_t, int [*][*][*]);
这可以写成:
int minimum(size_t, int (*)[*][*]);
甚至使用未指定大小的数组:
int minimum(size_t, int (*)[][*]);
但是你没有可能省略或绕过最后的指示,因此它必须保持[*]
这样的声明。