访问结构成员而不使用点运算符

Neo*_*low 3 c

我甚至都不知道,我所问的是不是愚蠢与否.我不是要求你为我编写任何代码,而是要以更好的方式做一些事情.

我有一个包含大量项目的结构,如下所示:

typedef struct _myStruct
{
    int int1;
    char char1;
    int int2;
    :
    :
    int int50;
}myStruct;
Run Code Online (Sandbox Code Playgroud)

我有另一个枚举,myStruct中的每个项目都有一个条目.

enum
{
   eINT1,
   eCHAR1,
   eINT2,
   :
   :
   eINT50
} PARAMETER_ID;
Run Code Online (Sandbox Code Playgroud)

我想为每种数据类型编写一个函数[比如说一个用于int,一个用于char,一个用于字符串等] myStruct,当PARAMETER_ID给出输入时,它返回一个成员的值.

例如,我需要一个int GetInt(PARAMETER_ID)函数,它返回int1eINT1作为参数传递时的值.同样我也会有char GetCharacter(PARAMETER_ID),float GetFloat(PARAMETER_ID)等等.

结构中的项目数可能很大.因此,为每个项目使用开关盒将不是一个可行的选择.

只有我能想到的其他选项是使用结构变量和offsetof()函数的地址来计算参数的地址,然后memcpy将所需的字节输入变量.在那种情况下,我需要在每个地方保留每个参数的偏移量,但这不是问题.

我正在寻找替代选项来做到这一点.任何帮助将不胜感激.

谢谢.

Bas*_*tch 5

大型switch是一个很好的可行选择.

您也可以玩预处理器技巧.

你可以有一个mystruct.def包含的文件

 INTFIELD(int1)
 CHARFIELD(char1)
 INTFIELD(int2)
Run Code Online (Sandbox Code Playgroud)

等...然后你会多次包括它; 声明结构:

 struct _myStruct {
 #define INTFIELD(F) int F;
 #define CHARFIELD(F) char F;
 #include "mystruct.def"
 #undef INTFIELD
 #undef CHARFIELD
 };
Run Code Online (Sandbox Code Playgroud)

声明枚举(使用e_int1而不是eINT1)

 enum field_en {
 #define INTFIELD(F) e_##F,
 #define CHARFIELD(F) e_##F,
 #include "mystruct.def"
 #undef INTFIELD
 #undef CHARFIELD
 };
Run Code Online (Sandbox Code Playgroud)

要实现访问者,

 int get_int(struct _myStruct*s, enum field_en f)
 {
    switch (f) {
 #define INTFIELD(F) case e_##F: return s->F;
 #define CHARFIELD(F) /*nothing*/
 #include "mystruct.def"
 #undef INTFIELD
 #undef CHARFIELD
    default: return 0;
 }}
Run Code Online (Sandbox Code Playgroud)

我并不认为这是更好或更易读的代码,但这种编程风格确实出现在某些C或C++程序中(例如GCC内部的代码gcc/tree.def)

如果您的代码是一个非常大的代码库,并且您已经准备好花上几天的时间(例如,因为您有很多这样的struct并且不想玩这样的技巧),您可以考虑使用MELT进行GCC扩展(高-level域特定语言来扩展GCC)来帮助你; 您可能可以进行MELT扩展以为您生成访问器功能.

你也可以说服你的老板同时生成structenum,并从一个特设的描述文件存取功能(使用awk,python或其他).GCC为其选项文件做了这样的技巧,例如gcc/common.opt

最后,如果包含该标题的标题_myStruct是如此神圣,以至于您不允许触摸它,并且如果格式非常干净,您可以制作一个特殊的(例如awk)脚本来获取该声明并对其进行处理.

NB一个好的编译器将密集switch语句优化为索引跳转,这需要花费一些时间,即使是数百种情况.