标量初始值设定项的多余元素,用于指向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;
…然后互换使用ptr
和arr
。 或这个:
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
的下一个数组。