【问题标题】:Static initialization of array of struct A, where struct A contains a pointer to array of struct B (in C)struct A 数组的静态初始化,其中 struct A 包含指向 struct B 数组的指针(在 C 中)
【发布时间】:2016-07-10 13:33:24
【问题描述】:

给定以下类型定义:

// Structures for kana to romaji conversion lookup
typedef struct {
  const u16 kana; // Kana codepoint
  const char* romaji;
} KanaSuffix;

typedef struct {
  // Kana codepoint is implied by position in array
  const char* romaji;
  const KanaSuffix* suffixes;
} KanaPrefix;

是否可以在一个步骤中静态初始化KanaPrefix 的数组,其中数组的某些元素有suffixes 指向KanaSuffix 的静态数组?

现在我正在这样做:

const KanaSuffix KANA_SUFFIXES_KI[] = {
  { 0x3030, "kya" },
  { 0x3032, "kyo" }
};

const KanaPrefix KANA_TO_ROMAJI[] = {
  { NULL, NULL },
  { "a", NULL },
  { "ki", KANA_SUFFIXES_KI }
};

但我想做更多这样的事情:

const KanaPrefix KANA_TO_ROMAJI[] = {
  { NULL, NULL },
  { "a", NULL },
  { "ki", {
    { 0x3030, "kya" },
    { 0x3032, "kyo" }
  } }
};

【问题讨论】:

  • 每个KanaPrefix 是否有相同数量的KanaSuffix
  • 很遗憾不是,但这是个好问题。

标签: c arrays struct


【解决方案1】:

你可以这样做:

const KanaPrefix KANA_TO_ROMAJI[] = {
  { NULL, NULL },
  { "a", NULL },
  { "ki",  (KanaSuffix [2]) {
      { 0x3030, "kya" },
      { 0x3032, "kyo" }
    }
  }
};

编辑

我可以[现在]确认这是已定义的行为,因为该复合文字的生命周期[或持续时间]与静态存储的相同:

C99 §6.5.2.5 复合文字

复合字面量的值是一个未命名对象的值 由初始化列表初始化。如果出现复合文字 在函数体之外,对象有静态存储 期间;否则,它具有与关联的自动存储持续时间 封闭块。

参考资料:

What is the lifetime of compound literals passed as arguments?

【讨论】:

  • 感谢您的回答,看起来不错!现在在我的手机上看这个,但我回家后会试试看。
【解决方案2】:

如果您只需要一个静态对象,那么您可以使用复合文字,因为如果在函数范围之外定义,则具有静态存储持续时间。

当然,由于结构 KanaPrefix 的成员 suffixes 指向多个元素,因此您也需要存储计数:

typedef struct {
  const char* romaji;
  const KanaSuffix* suffixes;
  const size_t count;   
} KanaPrefix;

const KanaPrefix KANA_TO_ROMAJI[] = {
  { NULL, NULL , 0 },
  { "a", NULL , 0 },
  { "ki", ( KanaSuffix[2] ){ //this is a compound literal
    { 0x3030, "kya" },
    { 0x3032, "kyo" }
  } , 2 }  //count is here
};

【讨论】:

  • 您可以在没有索引{ "ki", ( KanaSuffix[] ) { 的情况下使用复合文字,并且可以很好地捕捉计数。
  • @bsa 我不建议这样做。您应该为具有一些有意义名称的值使用宏,并将其用于复合文字和计数成员。
  • @2501 是非标准的吗?你不推荐它的原因是什么?
  • @2501 我明白了.. 我猜是因为它作为内置的编译时检查长度是否与计数匹配?我实际上是在自动生成定义,所以不太可能出错,但它仍然有助于防止我的生成代码中的错误或未来的手工修改。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-22
  • 1970-01-01
  • 1970-01-01
  • 2021-09-21
  • 1970-01-01
相关资源
最近更新 更多