C数组声明语法

时间:2018-12-24 18:38:12

标签: c arrays pointers declaration

在包含文件中声明一个数组,省略第一个尺寸:

extern float mvp[][4];

然后在翻译单元中的前一个声明之后定义数组:

float mvp[4][4];

没问题。直到尝试获取包含第一个声明的文件中该数组的大小为止。然后您将得到:

error: invalid application of 'sizeof' to an incomplete type 'float [][4]'

我知道数组在用作左值时会分解为指向其第一个元素的指针,函数原型中的数组声明实际上是伪装的指针,但事实并非如此。但是第一个声明没有声明指针,而是声明了一个不同于以下内容的“不完整数组类型”:

extern float (*mvp)[4];

声明变量时,编译器仅引用“虚拟”基地址偏移量以及链接程序将解析的关联类型。

我想知道为什么这种“不完整的数组类型”(它不能像指向数组的指针那样递增,但由于无法获取其大小而不能完全作为数组)将被允许存在吗?

为什么不将其隐式转换为指针(仅是基地址偏移量)甚至更好,为什么不为忽略一维尺寸而抛出错误?

2 个答案:

答案 0 :(得分:3)

使用extern不会使事物存在,它只是用来说明某些事物可能存在于不同的翻译单元中。 sizeof()仅可用于完整类型。这与数组指针衰减无关。 extern float (*mvp)[4]是一个完整类型,它是一个指向4个浮点数的数组的指针。 extern float mvp[][4]不完整,它是2D浮点数组,其中未指定维度之一。这是两件事。无论哪种情况,在使用正确的语法时,mvp都可以用作数组,但是只有在sizeof可以实际确定其大小的情况下,您才能使用它。

float mvp[][4]也是一个数组,只是其大小不确定。使它成为数组的原因是它的内存像数组一样布置。

答案 1 :(得分:2)

可以声明extern数组的所有尺寸:

extern float mvp[4][4];

这只是一个选择,可以使外部声明不完整,让定义担心尺寸。 精确很有用,因为大小不是其外部接口的一部分!如果最外层的大小从编译更改为另一个,则不必重新编译仅使用对象的转换单元。

要执行此操作,可能应该有一个定点值(sentinel value)结束数组/一个变量,该变量将告诉您有多少个元素,否则不是很有用。


  

为什么不将其隐式转换为指针(只是基地址偏移量)甚至更好,为什么不为忽略第一维尺寸而抛出错误?

由于声明不是定义,因此无法将其转换为指针。它只是告诉我们确实存在这样的对象。该对象的定义独立于外部声明而存在。在此声明的实际对象是一个数组,而不是一个指针。

只是在数组的情况下,外部声明可以声明最外面的维度或可以忽略它。


关于该主张

  

数组用作左值时会衰减为指向其第一个元素的指针

那是完全错误的。数组表达式是左值,当它衰减时不再是左值-唯一保持左值的情况就是&的操作数。