引用 C99 标准 §6.2.5 ¶20(类型)
数组类型描述了一个连续分配的非空集合
具有特定成员对象类型的对象,称为元素类型。
数组类型的特征在于它们的元素类型和数量
数组中的元素。
该标准在 §6.2.5 ¶22 中进一步说明
未知大小的数组类型是不完整类型。完成了,
对于该类型的标识符,通过在稍后指定大小
声明(带有内部或外部链接)。
数组下标运算符[] 的优先级高于* 运算符。因此,声明
char *argv[];
将argv 定义为一个指向未知大小字符的指针数组,因为未指定数组大小。数组argv 是不完整的类型。这是假设上述语句中的表达式没有作为函数参数出现。由于数组argv 是不完整类型,因此您必须在使用前提供其大小信息。这意味着您应该将上述语句作为声明并在其他地方提供其定义,以便链接器将解析它。阅读本文以了解声明和定义之间的区别 -
What is the difference between a definition and a declaration?
// array declaration.
// this does not allocate space
// but only provides type information
// though of an incomplete type.
// argv must have internal or external linkage.
extern char *argv[];
// definition of the array.
// complete information and
// allocates memory for it.
// in the same translation unit or
// a different one.
char *argv[8];
您还可以使用数组初始化器列表来初始化数组,并且将从列表中推断出数组的大小。
// size of the array argv is determined
// explicitly to be 2
char *argv[] = {"Hello", "World"};
// the above is equivalent to
char *argv[2];
argv[0] = "Hello";
argv[1] = "World";
注意:以上只是为了演示数组初始化而没有明确提及它的大小。字符串字面量是只读的,所以语句最好写成
const char *argv[] = {"Hello", "World"};
如果它作为函数参数出现,那么它相当于char **argv,如
int main(int argc; char *argv[]);
// equivalent to
int main(int argc, char **argv);
以下语句中的数组也是如此。
char argv[][7];
上述语句将argv定义为char[7]类型的元素数组,即7字符数组。同样,未指定数组argv 的大小。因此,argv 是一个不完整的类型。假设它不作为函数参数出现,则应将语句放入声明中,因为它是不完整的类型,应在其他地方提供其定义。
// array declaration.
// argv must have internal or external linkage
extern char argv[][7];
// definition.
// in the same translation unit
// or a different one
char argv[10][7];
数组可以像前一种情况一样初始化,大小将由初始化列表隐式确定。
// size of the array argv is inferred from
// the initializer list to be 3.
char argv[][7] = {{'a', 'b', 'c', 'd', 'e', 'f', 'g'},
{'a', 'b', 'c', 'd', 'e', 'f', 'g'},
{'a', 'b', 'c', 'd', 'e', 'f', 'g'}};
但是,如果数组表达式以函数参数的形式出现,则它等价于
char (*)[7],即指向7 字符数组的指针。
void foo(char argv[][7]);
// equivalent to
void foo(char (*)[7])
这是因为您不能将数组传递给函数。实际上传递的是指向数组第一个元素的指针。因此,函数中的数组参数被隐式转换为pointer to array element类型。请阅读本文了解更多详情 -
Why do C and C++ compilers allow array lengths in function signatures when they're never enforced?