C结构体数组的初始化

5
我有结构。
struct ABC {
  int a; 
  int b;
}

并将其作为数组

struct ABC xyz[100];

我想要初始化数组中所有元素为a = 10和b = 20。与此相关的IT技术如何更好地实现呢?

哪种方法更好?


3
写一个循环?有什么问题吗? - Guntram Blohm
3
请问这是需要翻译成中文吗?如果是,那么“write 100 times in your code!”可以翻译为“在你的代码中写下100次!” - Grijesh Chauhan
3
GCC扩展:struct ABC xyz[100] = {[0 ... 99] = {10, 20}}; 的意思是定义一个名为xyz的结构体数组,其中包含100个元素,每个元素都是结构体ABC类型。大括号中的[0 ... 99]用于初始化索引从0到99的所有元素,它们都被赋值为具有成员变量值10和20的结构体ABC。 - BLUEPIXY
5个回答

15

虽然在C语言中没有特别优雅的方法来初始化这样一个大数组,但是是可行的。正如某些答案错误地声称的那样,您不必在运行时进行初始化。而且,如果数组是const,您也不想在运行时进行初始化。

我使用的方法是定义一些宏:

struct ABC {
  int a; 
  int b;
};

#define ABC_INIT_100 ABC_INIT_50 ABC_INIT_50
#define ABC_INIT_50  ABC_INIT_10 ABC_INIT_10 ABC_INIT_10 ABC_INIT_10 ABC_INIT_10
#define ABC_INIT_10  ABC_INIT_2 ABC_INIT_2 ABC_INIT_2 ABC_INIT_2 ABC_INIT_2
#define ABC_INIT_2   ABC_INIT_1 ABC_INIT_1
#define ABC_INIT_1   {10, 20},

int main()
{
  struct ABC xyz[100] =
  {
    ABC_INIT_100
  };
}
注意,这样的宏可以以任何方式组合在一起,以进行任意数量的初始化。例如:
#define ABC_INIT_152 ABC_INIT_100 ABC_INIT_50 ABC_INIT_2

9

使用GCC,您可以使用其扩展语法并执行以下操作:

struct ABC xyz[100] = { [0 ... 99].a = 10, [0 ... 99].b = 20 };

对于一种便携式解决方案,我可能会初始化一个实例,并使用循环将该实例复制到其余部分:

struct ABC xyz[100] = { [0].a = 10, [0].b = 20 };

for(size_t i = 1; i < sizeof xyz / sizeof *xyz; ++i)
  xyz[i] = xyz[0];

对我来说,这比在循环中使用实际值更为清晰。它可以被认为是以稍微更高的层次表达所需的结果。

上述语法([0].a[0].b)不是扩展,它是典型的C99。


便携版严格来说并不是“初始化”,而是在运行时赋值。如果xyz是const的,你会如何处理呢? - Lundin
@Lundin 当然是真的,就像所有其他循环建议一样。我认为这不能用const完成,除非有一个巨大的显式初始化或宏(就像你的答案)。 - unwind
@lundin 另一方面,如果所讨论的数组是在函数内分配到栈上的,并且数组大小是一个函数参数,那么你会如何使用宏?你可以通过添加额外的要求来使任何答案都不适用,但没有迹象表明 OP 正在寻找一个 const 数组;考虑到问题的性质,他更可能只是在寻找一种避免大量输入的方法(你的解决方案和基于循环的解决方案都提供了这种方法)。虽然它不是严格的初始化,但在非正式场合下,这确实是大多数人所指的意思。 - JVMATL
此外,就我个人而言,我喜欢这个版本更好地捕捉了将所有元素设置为相同默认值的意图,并且如果数组的大小发生变化(或是动态的),它也不会出现问题。 - JVMATL
@JVMATL 本地作用域的可变长度数组在运行时分配,因此与其使用初始化而不是赋值相比,并没有任何好处。只有在涉及变量的默认值时,初始化和赋值之间的区别才有意义,这些值可以在编译时确定。 - Lundin
显示剩余6条评论

1
for(unsigned int i=0; i<100; i++)
{
    xyz[i].a = 10;
    xyz[i].b = 20;
}

严格来说,这不是“初始化”,而是运行时赋值。如果xyz是“const”,你会怎么做? - Lundin
@Lundin 为什么你需要同样的值超过一个副本呢? - Brave Sir Robin
@rmartinjak 这完全取决于应用程序的性质。假设存在一种情况,其中所有值都是独立的,而另一种情况则是它们都相同。然后,您可以将const数组用作函数的输入。 - Lundin

0

我不是C语言专家(所以如果你要来抓我的话...)

这个代码符合规范并且运行良好!

typedef struct
{
    double var1;
    double var2;
    double var3;
    double var4;
}VectorData;

#define MAX_INDEX 100

VectorData Data[] = {[0 ... MAX_INDEX] = {0.0, 0.0, 0.0, 0.0}};

这样可以从MAX_INDEX中推断出数组的大小。在这种情况下,您有一个包含101个元素的数组。


0

在数组子结构中,没有明确的语言支持来初始化所有元素为特定的非零默认值,就像初始化所有元素为零一样;您必须在编译时在源代码中显式地初始化每个元素,或者您必须编写一个for()循环并在启动时初始化每个元素。

正如用户@lundin在另一个答案中指出的那样,您可以使用预处理器宏来减少显式初始化这些值所涉及的输入,但就C编译器而言,您仍然在显式地初始化每个元素。


标准C语言中有相应的语法。你不需要在运行时使用循环。 - Lundin
更新了答案以澄清第一个版本明显误导的内容,@Lundin 的基于预处理器的解决方案很聪明,但我认为声称在标准C中存在“某些语言语法”只是因为你可以通过预处理器技巧实现某些东西有点牵强。预处理器行为可能会在标准中指定,但它并不是'C'本身。 - JVMATL
如果您可以使用完全符合C编译器的某些机制来完成它,那么就有相应的C语法。关于预处理器是否属于“C语法”,请参见标准的附录A中的“语言语法摘要” :) - Lundin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接