【发布时间】:2018-12-24 18:38:11
【问题描述】:
在包含文件中声明一个数组,省略第一个维度大小:
extern float mvp[][4];
然后在翻译单元中的前面声明之后定义数组:
float mvp[4][4];
没问题。直到您尝试在包含第一个声明的文件中获取该数组的大小。然后你会得到:
error: invalid application of 'sizeof' to an incomplete type 'float [][4]'
我知道数组在用作左值时会衰减为指向其第一个元素的指针,函数原型中的数组声明实际上是变相的指针,但情况并非如此。但是第一个声明没有声明一个指针,它声明了一个“不完整的数组类型”,不同于:
extern float (*mvp)[4];
在声明变量时,编译器只引用一个“虚拟”基地址偏移量和链接器将解析的关联类型。
我想知道为什么这种“不完整的数组类型”——它不能像指向数组的指针那样递增,但也不是完全的数组,因为它的大小无法检索——会被允许存在?
为什么不将其隐式转换为指针(只是基地址偏移量)甚至更好,为什么不抛出错误以省略第一维的大小?
引用this
如果数组声明器中的表达式被省略,它声明一个未知大小的数组。除了在函数参数列表中(此类数组被转换为指针)和初始化器可用时,此类类型是不完整类型(请注意,未指定大小的 VLA,以 * 作为大小声明,是完整类型)
实际上,类型是不完整的,等待稍后的声明或暂定定义来完成。
【问题讨论】:
-
“我知道数组在用作左值时会衰减为指向其第一个元素的指针” - 我不这么认为。您可能的意思是当作为函数参数传递时它们会衰减为指针?
-
当您使用数组的名称作为左值时,这意味着您想要引用内存存储而不是类型(并且您也不想创建右值)然后 数组将衰减为指向其第一个元素的指针.
-
@MichaelBeer:它们几乎在任何情况下都会衰减为指针(尽管不像问题描述的那样)。您正在考虑一种不同的机制,其中声明为数组类型的函数参数被自动定义为指针类型。
-
@user2357112
int b; int a[]; a = &b;-a在这里用作左值,但兼容的编译器不应该允许这样做,恕我直言。 -
@MichaelBeer:是的,那是无效的。我正在考虑当您执行
pointer = array或array[5]之类的操作时使数组衰减为指针的机制(是的,这涉及衰减),而您正在考虑将int foo(int arg[5])转换为int foo(int *arg)的机制.
标签: c arrays pointers declaration