指向int数组的指针的标量初始化器的多余元素

时间:2022-09-30 21:17:56

I’m working on an exercise in K&R (ex. 5–9) and I was trying to convert the original program’s 2D array of

我在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}
};

into using pointers to an array of 13 ints like

使用指针指向一个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}
};

But compiler prints warning: excess elements in scalar initializer.

但是编译器会输出警告:标量初始化器中的多余元素。

Googling did not help and even K&R writes when passing the array to a function,

google没有帮助,甚至K&R在将数组传递给函数时也会写,

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

is the same as

是一样的

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

2 个解决方案

#1


25  

The two are only partly equivalent. The difference being that:

两者只是部分等同。的区别是:

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}
};

declares a two-dimensional array, which includes setting aside space for the array and ensuring that daytab references that memory. However:

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

...only declares a pointer. So you're trying to initialize a pointer with an array initializer, which doesn't work as expected. There is no array; there's no memory set aside for an array. What happens instead is that the first number in your initializer is assigned to the pointer daytab, and the compiler generates a warning to let you know you've specified a lot of additional values that are just discarded. Since the first number in your initializer is 0, you're just setting daytab to NULL in a rather verbose way.

…只声明一个指针。因此,您正在尝试用数组初始化器初始化一个指针,这并不像预期的那样工作。没有数组;没有为数组预留内存。相反,初始化器中的第一个数字被分配给指针daytab,编译器生成一个警告,让您知道您已经指定了许多刚刚被丢弃的附加值。由于初始化器中的第一个数字是0,所以您只是以一种相当冗长的方式将daytab设置为NULL。

So if you want to do this sort of initialization, use the first version -- it decays to the same pointer type that you explicitly declare in the second version, so you can use it the same way. The second version, with the array pointer, is needed when you wish to dynamically allocate the array or get a reference to another array that already exists.

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

So you can do this:

你可以这样做:

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

ptr = arr;

...and then use ptr and arr interchangeably. Or this:

…然后交替使用ptr和arr。或:

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

ptr = malloc(2 * sizeof(*ptr));

...to get a dynamically allocated 2-dimensional array (not an array of pointers to 1D arrays, but a real 2D array). Of course, it's not initialized in that case.

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

The "equivalence" of the two variations just means that the 2D array, when it decays to a pointer to its first element, decays to the type of pointer declared in the second variation. Once the pointer version is actually pointed at an array, the two are equivalent. But the 2D array version sets up memory for the array, where the pointer declaration doesn't... and the pointer can be assigned a new value (pointed at a different array) where the 2D array variable cannot.

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

In C99 you can do this, though (if not static at least):

在C99中,你可以这样做(即使不是静态的):

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}
};

#2


0  

@Dmitri explained it well, but I wanted to add that

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

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

is a char pointer to an array of 13 chars. As K&R explained, without the parentheses, brackets [] have higher precedence, so

是指向13个字符的数组的字符指针。正如K&R所解释的,没有括号,括号[]具有更高的优先级

static char *daytab[2] { ... };

would produce the desired effect of having an array of 2 char pointers. Now we just need to initialize the two pointers to reference an appropriate char [] array.

将产生一个包含两个char指针的数组的期望效果。现在我们只需要初始化两个指针,以引用适当的char[]数组。

Option 1:

选项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}
    };

Option 2:

选项2:

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

#1


25  

The two are only partly equivalent. The difference being that:

两者只是部分等同。的区别是:

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}
};

declares a two-dimensional array, which includes setting aside space for the array and ensuring that daytab references that memory. However:

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

...only declares a pointer. So you're trying to initialize a pointer with an array initializer, which doesn't work as expected. There is no array; there's no memory set aside for an array. What happens instead is that the first number in your initializer is assigned to the pointer daytab, and the compiler generates a warning to let you know you've specified a lot of additional values that are just discarded. Since the first number in your initializer is 0, you're just setting daytab to NULL in a rather verbose way.

…只声明一个指针。因此,您正在尝试用数组初始化器初始化一个指针,这并不像预期的那样工作。没有数组;没有为数组预留内存。相反,初始化器中的第一个数字被分配给指针daytab,编译器生成一个警告,让您知道您已经指定了许多刚刚被丢弃的附加值。由于初始化器中的第一个数字是0,所以您只是以一种相当冗长的方式将daytab设置为NULL。

So if you want to do this sort of initialization, use the first version -- it decays to the same pointer type that you explicitly declare in the second version, so you can use it the same way. The second version, with the array pointer, is needed when you wish to dynamically allocate the array or get a reference to another array that already exists.

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

So you can do this:

你可以这样做:

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

ptr = arr;

...and then use ptr and arr interchangeably. Or this:

…然后交替使用ptr和arr。或:

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

ptr = malloc(2 * sizeof(*ptr));

...to get a dynamically allocated 2-dimensional array (not an array of pointers to 1D arrays, but a real 2D array). Of course, it's not initialized in that case.

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

The "equivalence" of the two variations just means that the 2D array, when it decays to a pointer to its first element, decays to the type of pointer declared in the second variation. Once the pointer version is actually pointed at an array, the two are equivalent. But the 2D array version sets up memory for the array, where the pointer declaration doesn't... and the pointer can be assigned a new value (pointed at a different array) where the 2D array variable cannot.

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

In C99 you can do this, though (if not static at least):

在C99中,你可以这样做(即使不是静态的):

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}
};

#2


0  

@Dmitri explained it well, but I wanted to add that

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

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

is a char pointer to an array of 13 chars. As K&R explained, without the parentheses, brackets [] have higher precedence, so

是指向13个字符的数组的字符指针。正如K&R所解释的,没有括号,括号[]具有更高的优先级

static char *daytab[2] { ... };

would produce the desired effect of having an array of 2 char pointers. Now we just need to initialize the two pointers to reference an appropriate char [] array.

将产生一个包含两个char指针的数组的期望效果。现在我们只需要初始化两个指针,以引用适当的char[]数组。

Option 1:

选项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}
    };

Option 2:

选项2:

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