简体   繁体   English

指向整数数组的指针的标量初始值设定项的多余元素

[英]Excess elements of scalar initializer for pointer to array of ints

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),并且我试图将原始程序的二维数组转换为

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,将数组传递给函数时,谷歌搜索没有帮助,甚至 K&R 写入,

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

is the same as是相同的

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

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.声明一个二维数组,其中包括为数组留出空间并确保daytab引用该内存。 However:然而:

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.相反,您的初始值设定项中的第一个数字被分配给指针daytab ,并且编译器生成一个警告,让您知道您已经指定了许多刚刚被丢弃的daytab Since the first number in your initializer is 0 , you're just setting daytab to NULL in a rather verbose way.由于初始化程序中的第一个数字是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. ...然后交替使用ptrarr Or this:或这个:

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.当然,在这种情况下它不会被初始化。

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.但是二维数组版本为数组设置了内存,其中指针声明没有......并且可以为指针分配一个新值(指向不同的数组),而二维数组变量则不能。

In C99 you can do this, though (if not static at least):但是,在 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 explained it well, but I wanted to add that @Dmitri 解释得很好,但我想补充一点

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

is one pointer to an array of 13 char elements.一个指向 13 个char元素数组的指针。 The compiler gives you the warning because you've passed in two arrays.编译器向您发出警告,因为您传入了两个数组。 It's like trying to assign two addresses to one pointer char *p = {a, b} .这就像尝试将两个地址分配给一个指针char *p = {a, b} There are more elements than necessary per your declaration.根据您的声明,元素过多。 See Geekforgeek's explanation on what an array pointer really means.请参阅Geekforgeek对数组指针真正含义的解释

As for answering the K&R exercise, consider至于回答 K&R 练习,请考虑

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

or Option 2:或选项 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}
    };} 

Option 1 is an array of two char pointers.选项 1 是一个包含两个char指针的数组。

Option 2 is one array pointer.选项 2 是一个数组指针。 It points to an array of 13 char elements.它指向一个包含 13 个char元素的数组。 Just as you could increment a char pointer to get the next letter in a string, you can increment this array pointer to grab the next array of 13 char s.就像你可以增加一个char指针来获取字符串中的下一个字母一样,你可以增加这个数组指针来获取下一个 13 个char的数组。

Just worked this problem in K&R myself, so maybe I can add to the really good answers already given.我自己刚刚在 K&R 中解决了这个问题,所以也许我可以添加到已经给出的非常好的答案中。 This is a good exercise in getting away from using 2-D arrays and towards using arrays of pointers.这是摆脱使用二维数组而转向使用指针数组的一个很好的练习。 Note that at this point in the book we have not been introduced to malloc .请注意,在本书的这一点上,我们还没有介绍malloc So, one approach would be to set up the month arrays beforehand, then an array of pointers to those arrays:因此,一种方法是预先设置月份数组,然后是指向这些数组的指针数组:

char y0[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
char y1[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
char *daytab[] = {y0, y1};

Recall that the name of an array is a pointer to the first element.回想一下,数组的名称是指向第一个元素的指针。 Now you really have an array of pointers to two arrays of 13 int s.现在你真的有一个指向两个 13 个int数组的指针数组。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM