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

ade*_*rtc 27 c arrays pointers

我正在研究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}
};
Run Code Online (Sandbox Code Playgroud)

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

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}
};
Run Code Online (Sandbox Code Playgroud)

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

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

myFunction(int daytab[2][13]) {...}
Run Code Online (Sandbox Code Playgroud)

是相同的

myFunction(int (*daytab)[13]) {...}
Run Code Online (Sandbox Code Playgroud)

Dmi*_*tri 30

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

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}
};
Run Code Online (Sandbox Code Playgroud)

声明一个二维数组,其中包括为数组预留空间并确保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}
};
Run Code Online (Sandbox Code Playgroud)

...只声明一个指针.因此,您尝试使用数组初始值设定项初始化指针,该指针无法按预期工作.没有阵列; 没有为阵列预留内存.相反的是,初始化程序中的第一个数字被分配给指针daytab,编译器会生成一个警告,通知您已经指定了许多刚丢弃的附加值.由于初始化程序中的第一个数字是0,您只是daytabNULL相当冗长的方式设置.

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

所以你可以这样做:

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

ptr = arr;
Run Code Online (Sandbox Code Playgroud)

......然后使用ptrarr互换.或这个:

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

ptr = malloc(2 * sizeof(*ptr));
Run Code Online (Sandbox Code Playgroud)

...获取动态分配的二维数组(不是指向一维数组的指针数组,而是一个真正的二维数组).当然,在这种情况下它没有初始化.

两个变体的"等价"仅意味着当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}
};
Run Code Online (Sandbox Code Playgroud)


khl*_*lau 7

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

static char (*daytab)[13] = { ... };
Run Code Online (Sandbox Code Playgroud)

一个指向 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}
    };} 
Run Code Online (Sandbox Code Playgroud)

或选项 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}
    };} 
Run Code Online (Sandbox Code Playgroud)

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

选项 2 是一个数组指针。它指向一个包含 13 个char元素的数组。正如您可以增加一个char指针以获取字符串中的下一个字母一样,您可以增加此数组指针以获取下一个 13char秒的数组。