C 工会成员如何拥有指向工会实例的指针?

C 工会成员如何拥有指向工会实例的指针?,c,pointers,arduino,C,Pointers,Arduino,我可能把这件事搞得太复杂了 我正试图用C语言在Arduino上为嵌入式应用程序创建一个可重用的分层菜单系统。我有一些结构来表示不同类型的菜单项,包括那些子菜单,这些子菜单的联合是一个通用菜单项。菜单项数组是菜单的一个级别。子菜单项具有指向另一个菜单项数组的指针 问题是,子菜单项是联合体的成员,因此需要在联合体之前定义它。但是它有一个指向此联合的实例数组的指针,这会导致编译错误,因为该联合尚未定义 是否有一种类型安全的方法来处理这个问题,或者子菜单项中的指针必须是void* 代码: 声明指向某些T

我可能把这件事搞得太复杂了

我正试图用C语言在Arduino上为嵌入式应用程序创建一个可重用的分层菜单系统。我有一些结构来表示不同类型的菜单项,包括那些子菜单,这些子菜单的联合是一个通用菜单项。菜单项数组是菜单的一个级别。子菜单项具有指向另一个菜单项数组的指针

问题是,子菜单项是联合体的成员,因此需要在联合体之前定义它。但是它有一个指向此联合的实例数组的指针,这会导致编译错误,因为该联合尚未定义

是否有一种类型安全的方法来处理这个问题,或者子菜单项中的指针必须是void*

代码:


声明指向某些
T
的指针只需要声明
T
,而不需要定义。那么就这么做吧:

union Entry;

typedef struct {
  char* entryName;
  const te_UIEntryType entryType = UI_ENTRY_SUBMENU;
  union Entry *entries[];
} ts_EntrySubmenu;

typedef union Entry {
  /* as before */
} tsEntry;

您需要转发declare
tuEntry
,以便在
ts\u entry子菜单中使用它。您需要为该联合指定一个标记名,以便以后可以引用它

此外,当结构或联合的字段在C中定义时,不能将其初始化为默认字段。您需要在每个相关实例中设置该字段

typedef union tuEntry tuEntry;

typedef struct {
  char* entryName;
  const te_UIEntryType entryType;   // no default value
  tuEntry *entries[];
} ts_EntrySubmenu;


union tuEntry
{
  tsEntry entry;
  ts_EntryInt entryInt;
  ts_EntrySingle entrySingle;
  ts_EntryBool entryBool;
  ts_EntryDiscrete entryDiscrete;
  ts_EntrySubmenu entrySubmenu;
};
问题是,子菜单项是联合体的成员,因此需要 在工会面前被定义

但它有一个指向数组的指针 此联合的实例,这会导致编译错误,因为 联盟还没有定义

声明指向该类型的指针不需要定义联合。它只需要被宣布。定义可以稍后再给出

有没有一种类型安全的方法来处理这个问题,或者我的指针是否在 子菜单项必须为空*

对。将联合声明在结构定义之前,并将联合定义放在后面。这确实需要为联合类型提供标记,否则转发声明和以后的定义将不会引用同一类型

例如:

typedef union entry tuEntry;

typedef struct {
  // ...
  tuEntry *entries[];
} ts_EntrySubmenu;


union entry
{
  // ...
  ts_EntrySubmenu entrySubmenu;
};


此外,我不能不注意到您的原始代码完全避免声明任何结构或联合标记。我想确保您理解这是一种样式选择,尤其是
typedef
关键字不是关于定义类型,而是关于为类型名声明别名。你的风格并非天生错误,但它并不支持你想做的事情。您需要使用带标记的结构和联合类型来链接同一范围内同一类型的多个声明。

我以为会有某种机制来实现这一点,但当我尝试时,并再次尝试从您的消息中剪切粘贴时,我收到一个编译错误“错误:声明冲突‘typedef union tuEntry tuEntry’”@CraigGraham您只能使用
typedef
一次。稍后定义联合时,只需定义它而不使用typedef。
typedef union entry tuEntry;

typedef struct {
  // ...
  tuEntry *entries[];
} ts_EntrySubmenu;


union entry
{
  // ...
  ts_EntrySubmenu entrySubmenu;
};