Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 不使用点运算符访问结构成员_C - Fatal编程技术网

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

C 不使用点运算符访问结构成员,c,C,我甚至不知道,我问的是不是愚蠢的问题。我不是要求你为我写任何代码,而是一个以更好的方式做某事的想法 我有一个包含大量如下项的结构: typedef struct _myStruct { int int1; char char1; int int2; : : int int50; }myStruct; 我有另一个枚举,它对myStruct中的每个项都有一个条目 enum { eINT1, eCHAR1, eINT2, :

我甚至不知道,我问的是不是愚蠢的问题。我不是要求你为我写任何代码,而是一个以更好的方式做某事的想法

我有一个包含大量如下项的结构:

typedef struct _myStruct
{
    int int1;
    char char1;
    int int2;
    :
    :
    int int50;
}myStruct;
我有另一个枚举,它对myStruct中的每个项都有一个条目

enum
{
   eINT1,
   eCHAR1,
   eINT2,
   :
   :
   eINT50
} PARAMETER_ID;
我想为每种数据类型编写一个函数[比如一个用于int,一个用于char,一个用于string等],当
参数ID作为输入时,它返回
myStruct
的一个成员的值

例如,我需要一个
intgetint(PARAMETER\u ID)
函数,当eINT1作为参数传递时,该函数返回
int1
的值。类似地,我将使用
char-GetCharacter(PARAMETER\u ID)
float-GetFloat(PARAMETER\u ID)

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

我能想到的唯一其他选择是使用结构变量的地址和
offsetof()
函数来计算参数的地址,然后通过
memcpy
将所需的字节输入变量。在这种情况下,我需要将每个参数的偏移量保持在某个位置,但这不是问题

我正在寻找其他的选择来做到这一点。任何帮助都将不胜感激


谢谢。

一个大的
开关是一个很好的可行选择

您还可以玩预处理器的把戏

您可以有一个
mystruct.def
文件,其中包含

 INTFIELD(int1)
 CHARFIELD(char1)
 INTFIELD(int2)
等等。。。然后你会把它包括好几次;要声明结构,请执行以下操作:

 struct _myStruct {
 #define INTFIELD(F) int F;
 #define CHARFIELD(F) char F;
 #include "mystruct.def"
 #undef INTFIELD
 #undef CHARFIELD
 };
声明枚举(使用
e_int1
而不是
eINT1

要实现访问器

 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;
 }}
< >我不认为这是更好的或更可读的代码,但是这种编程风格确实出现在一些C或C++程序中(例如GCC内部代码及其代码> Gcc/Trime.DEF)

如果你的代码是一个非常大的代码库,并且你准备好花上几天的时间(例如,因为你有很多这样的代码> Stult,不想玩这样的把戏),你可以考虑用一个GCC扩展(一个高级的特定领域的语言来扩展GCC)来帮助你;您可能可以进行MELT扩展来为您生成访问器函数

您还可以说服上司从一个特殊的描述性文件(使用
awk
python
或其他方法)生成
struct
enum
和accessor函数。GCC对其选项文件执行此类操作,例如,
GCC/common.opt

最后,如果包含
\u myStruct
的标题非常神圣,不允许您触摸它,并且如果它的格式非常干净,您可以制作一个临时脚本(例如
awk
)来获取该声明并对其进行处理


注意:一个好的编译器会将密集的
switch
语句优化为索引跳转,这需要恒定的时间,即使在数百种情况下也是如此。

您可以部分回答自己的问题,
offsetof
就是为了这个目的而使用的。必须考虑结构填充/对齐方式。我想你正在寻找类似的东西:

#include <stddef.h>  // size_t, offsetof
#include <string.h>  // memcpy
#include <stdio.h>

typedef struct
{
  int  int1;
  char char1;
  int  int2;
  int  int50;
} myStruct;

typedef enum
{
  eINT1,
  eCHAR1,
  eINT2,
  eINT50,
  ITEMS_IN_STRUCT
} myEnum;


static const size_t MYSTRUCT_MEMBER_OFFSET [ITEMS_IN_STRUCT] =
{
  offsetof(myStruct, int1),
  offsetof(myStruct, char1),
  offsetof(myStruct, int2),
  offsetof(myStruct, int50),
};

static const myStruct MS;
static const size_t MYSTRUCT_MEMBER_SIZE [ITEMS_IN_STRUCT] = 
{
  sizeof(MS.int1),
  sizeof(MS.char1),
  sizeof(MS.int2),
  sizeof(MS.int50)
};



void myStruct_get_member (void* result, const myStruct* ms, myEnum id)
{
  memcpy (result, 
          (char*)ms + MYSTRUCT_MEMBER_OFFSET[id], 
          MYSTRUCT_MEMBER_SIZE[id]);
}
#包括//尺寸、偏移量
#包括//memcpy
#包括
类型定义结构
{
int int1;
char-char1;
int int2;
int50;
}我的结构;
类型定义枚举
{
eINT1,
eCHAR1,
eINT2,
eINT50,
结构中的项目
}髓鞘;
静态常量大小\u t MYSTRUCT\u成员\u偏移量[结构中的项目]=
{
偏移量(myStruct,int1),
抵消(我的合同,第1章),
offsetof(myStruct,int2),
偏移量(myStruct,int50),
};
静态常量myStruct MS;
静态常量大小\u t MYSTRUCT\u成员大小[结构中的项目]=
{
sizeof(MS.int1),
sizeof(char1女士),
sizeof(MS.int2),
sizeof(MS.int50)
};
void myStruct\u get\u成员(void*result,const myStruct*ms,myEnum id)
{
memcpy(结果,
(char*)ms+MYSTRUCT成员偏移量[id],
MYSTRUCT_成员_大小[id]);
}
#包括
#包括
结构
{
int int1;
char-char1;
int int2;
char-char2;
龙龙1;
}myStruct={12345,'A',321,'B',-1L};
枚举
{
eINT1=偏移量(结构S,int1),
eCHAR1=偏移量(结构S,字符1),
eINT2=偏移量(结构S,int2),
eCHAR2=偏移量(结构S,字符2),
长度1=偏移量(结构S,长度1),
}参数ID;
char GetChar(int para_id)
{
return*((char*)((char*)&myStruct+para_id));
}
int GetInt(int para_id)
{
返回*((int*)((char*)&myStruct+para_id));
}
long GetLong(int para_id)
{
返回*((长*)((字符*)&myStruct+para_id));
}
真空总管(真空)
{
printf(“int1的偏移量=%d\n”,eINT1);
printf(“字符1的偏移量=%d\n”,eCHAR1);
printf(“int2的偏移量=%d\n”,eINT2);
printf(“字符2的偏移量=%d\n”,eCHAR2);
printf(“长偏移量1=%d\n”,长1);
printf(“int1=%d\n”,GetInt(eINT1));
printf(“char1=%c\n”,GetChar(eCHAR1));
printf(“int2=%d\n”,GetInt(eINT2));
printf(“char2=%c\n”,GetChar(eCHAR2));
printf(“long1=%ld\n”,GetLong(eLONG1));
}

您考虑过阵列吗?使用大型
开关是一个很好的可行选择。。。。我相信你拒绝它是错误的…@谢谢。我理解。但我的老板不希望我每次引入新参数时都修改这些函数:(.如果您采用您描述的地址路径,您不需要这样做吗?这些奇怪的结构来自何处?如果您需要以这种方式访问它们,它们是如何以这种方式设计的?@cnicutar:这都是现有代码库的一部分,我不允许修改基本实现,因为它与oth有一些依赖关系呃,代码的一部分。先生,很好。我知道这件事
不是那么容易做到。从所有人的评论来看,我认为这个设计很糟糕。所以我正在考虑在老板允许的情况下对设计进行更改,以便我可以
#include <stddef.h>  // size_t, offsetof
#include <string.h>  // memcpy
#include <stdio.h>

typedef struct
{
  int  int1;
  char char1;
  int  int2;
  int  int50;
} myStruct;

typedef enum
{
  eINT1,
  eCHAR1,
  eINT2,
  eINT50,
  ITEMS_IN_STRUCT
} myEnum;


static const size_t MYSTRUCT_MEMBER_OFFSET [ITEMS_IN_STRUCT] =
{
  offsetof(myStruct, int1),
  offsetof(myStruct, char1),
  offsetof(myStruct, int2),
  offsetof(myStruct, int50),
};

static const myStruct MS;
static const size_t MYSTRUCT_MEMBER_SIZE [ITEMS_IN_STRUCT] = 
{
  sizeof(MS.int1),
  sizeof(MS.char1),
  sizeof(MS.int2),
  sizeof(MS.int50)
};



void myStruct_get_member (void* result, const myStruct* ms, myEnum id)
{
  memcpy (result, 
          (char*)ms + MYSTRUCT_MEMBER_OFFSET[id], 
          MYSTRUCT_MEMBER_SIZE[id]);
}
#include <stddef.h>
#include <stdio.h>

struct S
{
 int  int1;
 char char1;
 int  int2;
 char char2;
 long long1;
} myStruct = {12345, 'A', 321, 'B', -1L};

enum
{
 eINT1  = offsetof(struct S, int1),
 eCHAR1 = offsetof(struct S, char1),
 eINT2  = offsetof(struct S, int2),
 eCHAR2 = offsetof(struct S, char2),
 eLONG1 = offsetof(struct S, long1),
} PARAMETER_ID;

char GetChar(int para_id)
{
  return *((char*)((char *)&myStruct + para_id));
}

int GetInt(int para_id)
{
  return *((int*)((char *)&myStruct + para_id));
}

long GetLong(int para_id)
{
  return *((long*)((char *)&myStruct + para_id));
}

void main(void)
{
  printf("offsetof int1  = %d\n", eINT1);
  printf("offsetof char1 = %d\n", eCHAR1);
  printf("offsetof int2  = %d\n", eINT2);
  printf("offsetof char2 = %d\n", eCHAR2);
  printf("offsetof long1 = %d\n", eLONG1);


  printf("int1  = %d\n",  GetInt (eINT1));
  printf("char1 = %c\n",  GetChar(eCHAR1));
  printf("int2  = %d\n",  GetInt (eINT2));
  printf("char2 = %c\n",  GetChar(eCHAR2));
  printf("long1 = %ld\n", GetLong(eLONG1));
}