【发布时间】:2019-07-21 22:56:24
【问题描述】:
我有一个只有一个成员的结构。这个成员实际上是一个指向整数的指针,用来表示一个二维整数数组。
我可以在创建该结构的实例时使用标量初始化吗?
我正在尝试创建一个二维数组来表示用于算法练习的像素集合。
我应该代表这样的东西:
{
{ 0, 0, 1, 0, 0 },
{ 0, 1, 1, 1, 0 },
{ 1, 1, 1, 1, 1 }
}
为了表示图像的通用抽象,我尝试创建具有以下结构的结构:
struct image_t
{
unsigned short int** pixels;
};
所以我尝试使用以下方法初始化一个实例:
int
main()
{
struct image_t image = {
{
{0, 0, 1, 0, 0},
{0, 1, 1, 1, 0},
{1, 1, 1, 1, 1},
}
};
return 0;
}
当我尝试编译时,会给出以下警告:
gcc -I src src/main.c -o bin/flood-fill.bin
src/main.c: In function ‘main’:
src/main.c:41:5: warning: braces around scalar initializer
{
^
src/main.c:41:5: note: (near initialization for ‘image.pixels’)
src/main.c:42:7: warning: braces around scalar initializer
{0, 1, 0},
^
src/main.c:42:7: note: (near initialization for ‘image.pixels’)
src/main.c:42:11: warning: excess elements in scalar initializer
{0, 1, 0},
^
src/main.c:42:11: note: (near initialization for ‘image.pixels’)
src/main.c:42:14: warning: excess elements in scalar initializer
{0, 1, 0},
在进行了一些研究后,我意识到,由于它将是一个图像表示,每一行将有相同的列总数。因此,我可以只使用一个数组并将所有内容存储在一个内存块中。 它解决了我的问题。
但是,作为一个好奇的人,我想知道在这种情况下是否有任何方法可以使用标量初始化 - 如果有,我该怎么做?
很可能我遗漏了 C 语言中的一些关键的基本概念,因此非常欢迎解释。我真的很想更好地了解它的工作原理。
【问题讨论】:
-
编译器会警告您有关标量初始值设定项中的多余元素,因为它期望
pixels有一个初始值,而您有一个用大括号括起来的列表。外大括号很好;image是一个结构体,它的初始值应该用大括号括起来。在这些里面,应该有一个值,pixels的初始值。由于pixels是unsigned short **,因此初始值应该是指向unsigned short的指针的指针或空指针。pixels是一个指针,所以你不能用一个数组来初始化它。 -
当然,您可以使用标量初始化——
pixels是一个标量,因此,要对其进行初始化,请给出一个值。但这不是你真正想要的。您对unsigned short** pixels的声明表明您希望像素是一个二维数组,并且您被建议误导使用指向指针的指针来形成二维数组。一般来说,二维数组应该是数组数组(静态分配或自动分配时)或指向数组的指针(动态分配时,如malloc)。 -
在您的情况下,如果列数是常量(使用
#define定义)Columns,您可以通过将pixels的声明更改为unsigned short (*pixels)[Columns];来开始。然后用数据创建一个数组,就像unsigned short MyData[Rows][Columns] = { { 0, 0, 1, 0, 0 }, { 0, 1, 1, 1, 0 }, { 1, 1, 1, 1, 1 } };一样,然后用struct image_t image = { MyData };定义image。可以对此进行改进,但这是一种合理的开始方式。 -
非常感谢您的回答,@EricPostpischil。由于我之前对数组(没有任何显式索引)的了解是指向其第一项的指针,因此我造成了这种混淆。这就是为什么我认为这个设计是正确的。现在它更干净了,因为它没有按预期工作。