标量初始值设定项的多余元素,用于指向int数组的指针

我正在研究K&R(例如5-9),我试图转换原始程序的2D数组

static char daytab[2][13] = { {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} }; 

使用指向13个int数组的指针

 static char (*daytab)[13] = { {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} }; 

但编译器会打印警告:标量初始化程序中的多余元素

谷歌搜索没有帮助,甚至K&R在将数组传递给函数时写道,

 myFunction(int daytab[2][13]) {...} 

是相同的

 myFunction(int (*daytab)[13]) {...} 

这两者只是部分相同。 不同之处在于:

 static char daytab[2][13] = { {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} }; 

声明一个二维数组,其中包括为数组预留空间并确保daytab引用该内存。 然而:

 static char (*daytab)[13] = { {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} }; 

…只声明一个指针。 所以你试图用一个数组初始化器初始化一个指针,它不能按预期工作。 没有arrays; 没有为数组预留内存。 相反的是,初始化程序中的第一个数字被分配给指针daytab ,编译器会生成一个警告,告诉您已经指定了许多刚丢弃的daytab 。 由于初始值设定daytab的第一个数字为0 ,因此您只需将daytab设置为NULL

因此,如果您想进行这种初始化,请使用第一个版本 – 它会衰减到您在第二个版本中明确声明的相同指针类型,因此您可以使用相同的方式。 当您希望动态分配数组或获取对已存在的另一个数组的引用时,需要使用数组指针的第二个版本。

所以你可以这样做:

 static char arr[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } }; static char (*ptr)[3] = NULL; ptr = arr; 

…然后互换使用ptrarr 。 或这个:

 static char (*ptr)[3] = NULL; ptr = malloc(2 * sizeof(*ptr)); 

…获取动态分配的2维数组(不是指向1D数组的指针数组,而是实际的2D数组)。 当然,在这种情况下它没有初始化。

两个变体的“等价”仅意味着当2D数组衰减到指向其第一个元素的指针时,它会衰减到第二个变体中声明的指针类型。 一旦指针版本实际指向数组,两者是等价的。 但是2D数组版本为数组设置了内存,其中指针声明没有……并且可以为指针指定一个新值(指向不同的数组),而2D数组变量则不能。

在C99中你可以做到这一点(至少不是static的):

 char (*daytab)[13] = (char [][13]){ {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} }; 

@Dmitri解释得很好,但我想补充一点

 static char (*daytab)[13] = { ... }; 

一个指向13个char元素数组的指针。 编译器会向您发出警告,因为您已传入两个数组。 这就像尝试将两个地址分配给一个指针char *p = {a, b} 。 根据您的声明,有多个元素不必要。 请参阅Geekforgeek关于数组指针真正含义的解释 。

至于回答K&R练习,请考虑

选项1:

 static char *daytab[2] = { (char []) {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, (char []) {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} };} 

或选项2:

 static char (*daytab)[13] = (char [][13]) { {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} };} 

选项1是两个char指针的数组。

选项2是一个数组指针。 它指向一个由13个char元素组成的数组。 就像你可以增加一个char指针来获取字符串中的下一个字母一样,你可以增加这个数组指针以获取13个char的下一个数组。