3

Given the following typedefs:

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

Is it possible to initialize an array of KanaPrefix statically in a single step, where some elements of the array have suffixes pointing to a static array of KanaSuffix?

Now I'm doing this:

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

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

But I want to do something more like this:

const KanaPrefix KANA_TO_ROMAJI[] = {
  { NULL, NULL },
  { "a", NULL },
  { "ki", {
    { 0x3030, "kya" },
    { 0x3032, "kyo" }
  } }
};
pah
  • 4,700
  • 6
  • 28
  • 37
bsa
  • 2,671
  • 21
  • 31

2 Answers2

6

You can do something like:

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

EDIT:

I can [now] confirm this is defined behaviour, since the lifetime [or duration] of that compound literal is the same as of static storage:

C99 §6.5.2.5 Compound literals

The value of the compound literal is that of an unnamed object initialized by the initializer list. If the compound literal occurs outside the body of a function, the object has static storage duration; otherwise, it has automatic storage duration associated with the enclosing block.

References:

What is the lifetime of compound literals passed as arguments?

Community
  • 1
  • 1
pah
  • 4,700
  • 6
  • 28
  • 37
  • Thanks for the answer, that looks good! Looking at this on my phone now but will try it out when I get home. – bsa Jul 10 '16 at 23:48
6

If all you need is a static object, then you can use compound literals, since if defined outside of a function scope, have static storage duration.

Of course since the member suffixes of the struct KanaPrefix is pointing to more than one element you will need to store the count too:

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
};
2501
  • 25,460
  • 4
  • 47
  • 87
  • You can do the compound literal w/o the index `{ "ki", ( KanaSuffix[] ) {`, and great catch of the count. – David C. Rankin Jul 11 '16 at 02:40
  • @bsa I don't recommend that. You should use a macro for the value with some meaningful name and use it on both the compound literal and the count member. – 2501 Jul 11 '16 at 12:56
  • @2501 Is it non-standard? What's the reason you don't recommend it? – bsa Jul 11 '16 at 13:03
  • 1
    @2501 I see.. I guess because it acts as a built-in compile-time check that the length matches the count right? I'm actually generating the definition automatically, so a mistake is unlikely, but it will still help to guard against mistakes in my generation code, or future hand modifications. Thanks! – bsa Jul 11 '16 at 13:10