如何在结构中定义结构并重复使用相同的名称两次?
How to define a struct in a struct and reuse the same name twice?
我有一个简单的 C 代码示例,在 struct
.
中使用 struct
- 我需要文档 (doxygen) 一个 named 结构,在我的示例中
HermannS
.
- 在doxygen中我可以用
\ref ottoS::HermannS::age
引用age
。
- 在doxygen中我可以不能使用
\ref ottoS.name.age
等
- 对于逻辑,名称
HermannS
必须相同。
问题:但是现在代码创建了一个重定义错误
struct ottoS {
struct HermannS {
int age;
} name;
};
struct otherS {
struct HermannS {
int size;
} name;
};
int main ()
{
return 0;
}
我收到以下错误消息:
main.c:16:10: error: redefinition of ‘struct HermannS’
struct HermannS {
^~~~~~~~
main.c:10:10: note: originally defined here
struct HermannS {
^~~~~~~~
问题:如何在struct
中定义struct
并重用名称HermannS
?
更好的问题:是否有 gcc 扩展(前缀)来隐藏此错误?
→ 但是对于一个简单的 doxygen 文档问题来说,这是一个非常 high 的代价。
你不能,正如编译器告诉你的那样,你也确实不需要。如果您没有在其他任何地方使用该结构,请不要命名它:
struct ottoS {
struct {
int age;
} name;
};
struct otherS {
struct {
int size;
} name;
};
唯一的其他(显而易见的)解决方案是对两个内部结构进行不同的命名。
如果您的 logic/code/documentation 是基于您需要这两个 不同的 结构具有相同名称的事实,那么我建议重新审视逻辑,因为它看起来有缺陷。
is there a gcc extension (prefix) to hide this error?
不,没有。这不是一个简单的错误,而是无效的 C 代码:您实际上是在同一个名称下定义了两种不同的类型。除非您避免这种情况,否则编译器将无法编译您的代码。
struct
声明不会像在 C++ 中那样在 C 中创建新的名称空间,因此您不能创建对 struct
类型来说是“本地”的类型名称。标签名称 HermannS
只能用于一个 struct
类型定义。
C 有四个名称空间:
- 所有标签(由
:
或 goto
消除歧义);
- 所有标签名称(由
struct
、union
或 enum
消除歧义)
- 成员名称(由
.
或 ->
消除歧义)
- 所有其他名称(typedef 名称、枚举常量、变量名称、函数名称等)
不幸的是,您尝试执行的操作在 C 中不起作用 - 您必须为每个内部结构定义使用不同的标记名称。
C 标准在第 6.7.2.1 节第 8 节中说
The presence of a struct-declaration-list in a
struct-or-union-specifier declares a new type, within a translation
unit.
所以所有 同一个翻译单元中的结构共享同一个命名空间。
HermannS
被重新定义,因此代码格式错误。
一些解决方法是添加带有父结构名称的前缀:
struct ottoS {
struct ottoS_HermannS {
int age;
} name;
};
struct otherS {
struct otherS_HermannS {
int size;
} name;
};
最新的 C 标准允许实现接受扩展集中的字符,如 $
。这将有助于避免与更传统的名称发生冲突。它适用于 gcc。但是,代码将不再可移植。
struct ottoS {
struct ottoS$HermannS {
int age;
} name;
};
struct otherS {
struct otherS$HermannS {
int size;
} name;
};
它有点模仿 C++ 中的 ::
运算符。您可以使用其他一些 unicode 字符,并使用它通过类似 sed 的工具对您的 Doxygen 文档进行后处理。我的意思是用 ::
.
替换魔法字符
由于程序格式错误,因此无法编译。但是,如果 struct HermannS
除了声明之外从未使用过,那么您可以使用以下技巧。
如果删除 HermannS
,则 ottoS.name
和 otherS.name
将变为 匿名结构 并且代码将编译。所有匿名结构都是独立的类型。只需将 -DHermannS=
传递给 GCC 的命令即可。
gcc prog.c -DHermannS=
它将添加一个扩展为空标记的宏 HermannS
。
不要不要将此选项传递给 doxygen 以让它生成正确的文档。
我有一个简单的 C 代码示例,在 struct
.
struct
- 我需要文档 (doxygen) 一个 named 结构,在我的示例中
HermannS
. - 在doxygen中我可以用
\ref ottoS::HermannS::age
引用age
。 - 在doxygen中我可以不能使用
\ref ottoS.name.age
等 - 对于逻辑,名称
HermannS
必须相同。
问题:但是现在代码创建了一个重定义错误
struct ottoS {
struct HermannS {
int age;
} name;
};
struct otherS {
struct HermannS {
int size;
} name;
};
int main ()
{
return 0;
}
我收到以下错误消息:
main.c:16:10: error: redefinition of ‘struct HermannS’
struct HermannS {
^~~~~~~~
main.c:10:10: note: originally defined here
struct HermannS {
^~~~~~~~
问题:如何在struct
中定义struct
并重用名称HermannS
?
更好的问题:是否有 gcc 扩展(前缀)来隐藏此错误? → 但是对于一个简单的 doxygen 文档问题来说,这是一个非常 high 的代价。
你不能,正如编译器告诉你的那样,你也确实不需要。如果您没有在其他任何地方使用该结构,请不要命名它:
struct ottoS {
struct {
int age;
} name;
};
struct otherS {
struct {
int size;
} name;
};
唯一的其他(显而易见的)解决方案是对两个内部结构进行不同的命名。
如果您的 logic/code/documentation 是基于您需要这两个 不同的 结构具有相同名称的事实,那么我建议重新审视逻辑,因为它看起来有缺陷。
is there a gcc extension (prefix) to hide this error?
不,没有。这不是一个简单的错误,而是无效的 C 代码:您实际上是在同一个名称下定义了两种不同的类型。除非您避免这种情况,否则编译器将无法编译您的代码。
struct
声明不会像在 C++ 中那样在 C 中创建新的名称空间,因此您不能创建对 struct
类型来说是“本地”的类型名称。标签名称 HermannS
只能用于一个 struct
类型定义。
C 有四个名称空间:
- 所有标签(由
:
或goto
消除歧义); - 所有标签名称(由
struct
、union
或enum
消除歧义) - 成员名称(由
.
或->
消除歧义) - 所有其他名称(typedef 名称、枚举常量、变量名称、函数名称等)
不幸的是,您尝试执行的操作在 C 中不起作用 - 您必须为每个内部结构定义使用不同的标记名称。
C 标准在第 6.7.2.1 节第 8 节中说
The presence of a struct-declaration-list in a struct-or-union-specifier declares a new type, within a translation unit.
所以所有 同一个翻译单元中的结构共享同一个命名空间。
HermannS
被重新定义,因此代码格式错误。
一些解决方法是添加带有父结构名称的前缀:
struct ottoS {
struct ottoS_HermannS {
int age;
} name;
};
struct otherS {
struct otherS_HermannS {
int size;
} name;
};
最新的 C 标准允许实现接受扩展集中的字符,如 $
。这将有助于避免与更传统的名称发生冲突。它适用于 gcc。但是,代码将不再可移植。
struct ottoS {
struct ottoS$HermannS {
int age;
} name;
};
struct otherS {
struct otherS$HermannS {
int size;
} name;
};
它有点模仿 C++ 中的 ::
运算符。您可以使用其他一些 unicode 字符,并使用它通过类似 sed 的工具对您的 Doxygen 文档进行后处理。我的意思是用 ::
.
由于程序格式错误,因此无法编译。但是,如果 struct HermannS
除了声明之外从未使用过,那么您可以使用以下技巧。
如果删除 HermannS
,则 ottoS.name
和 otherS.name
将变为 匿名结构 并且代码将编译。所有匿名结构都是独立的类型。只需将 -DHermannS=
传递给 GCC 的命令即可。
gcc prog.c -DHermannS=
它将添加一个扩展为空标记的宏 HermannS
。
不要不要将此选项传递给 doxygen 以让它生成正确的文档。