我甚至都不知道,我所问的是不是愚蠢与否.我不是要求你为我编写任何代码,而是要以更好的方式做一些事情.
我有一个包含大量项目的结构,如下所示:
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将所需的字节输入变量.在那种情况下,我需要在每个地方保留每个参数的偏移量,但这不是问题.
我正在寻找替代选项来做到这一点.任何帮助将不胜感激.
谢谢.
大型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扩展以为您生成访问器功能.
你也可以说服你的老板同时生成struct的enum,并从一个特设的描述文件存取功能(使用awk,python或其他).GCC为其选项文件做了这样的技巧,例如gcc/common.opt
最后,如果包含该标题的标题_myStruct是如此神圣,以至于您不允许触摸它,并且如果格式非常干净,您可以制作一个特殊的(例如awk)脚本来获取该声明并对其进行处理.
NB一个好的编译器将密集switch语句优化为索引跳转,这需要花费一些时间,即使是数百种情况.