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

发布于 2024-12-15 07:54:19 字数 660 浏览 0 评论 0原文

我正在 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 个整数数组的指针,例如

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]) {...}

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

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

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,

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

is the same as

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

蓦然回首 2024-12-22 07:54:19

两者仅部分等效。区别在于:

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

...仅声明一个指针。因此,您尝试使用数组初始值设定项初始化指针,但这无法按预期工作。没有数组;没有为数组留出内存。相反,发生的情况是初始化程序中的第一个数字被分配给指针 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));

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

两个变体的“等价性”仅意味着二维数组在衰减为指向其第一个元素的指针时,衰减为第二个变体中声明的指针类型。一旦指针版本实际指向数组,两者就等效。但是 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}
};

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:

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.

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:

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):

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}
};
寒江雪… 2024-12-22 07:54:19

@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 的数组。

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

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

is one pointer to an array of 13 char elements. 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}. There are more elements than necessary per your declaration. See Geekforgeek's explanation on what an array pointer really means.

As for answering the K&R exercise, consider

Option 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:

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.

Option 2 is one array pointer. It points to an array of 13 char elements. 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 chars.

不奢求什么 2024-12-22 07:54:19

我自己刚刚在 K&R 中解决了这个问题,所以也许我可以添加到已经给出的非常好的答案中。这是摆脱使用二维数组而转向使用指针数组的一个很好的练习。请注意,在本书中,我们还没有介绍过malloc。因此,一种方法是预先设置月份数组,然后设置指向这些数组的指针数组:

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

回想一下,数组的名称是指向第一个元素的指针。现在您确实拥有了一个指向两个 13 个 int 数组的指针数组。

Just worked this problem in K&R myself, so maybe I can add to the really good answers already given. 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. 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 ints.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文