简体   繁体   English

使用 int 或 enum 值访问结构字段

[英]Accessing a struct field using an int or enum value

I currently use a logging system that uses a tag value to identify the parameter that it will store.我目前使用一个日志系统,它使用标签值来识别它将存储的参数。 The format we are using is the following: Tag + Time + value.我们使用的格式如下:Tag + Time + value。

The next step is to take a logged message and send it to a server using Protocol Buffers to serialize the data.下一步是获取记录的消息并将其发送到使用协议缓冲区的服务器以序列化数据。

The protocol buffer.proto file, provides a struct with all the fields each corresponding to a tag in the original logging system. protocol buffer.proto 文件提供了一个结构体,其中包含所有字段,每个字段对应于原始日志系统中的一个标记。

The problem comes when I need to efficiently read the tag and assign the value to a field in the protocol buffer struct.当我需要有效地读取标签并将值分配给协议缓冲区结构中的字段时,问题就出现了。 In essence I would for example like to take in tag 5 and be able to find the field 5 in the struct and write the value.本质上,我想例如接受标签 5 并能够在结构中找到字段 5 并写入值。

I know this could be done with switch cases, but we are using around 50 tags so I would like to avoid this solution if possible.我知道这可以通过 switch case 来完成,但我们使用了大约 50 个标签,所以我想尽可能避免使用这种解决方案。 I attach an example struct to illustrate the problem.我附上了一个示例结构来说明这个问题。

/* Struct definitions */
typedef struct _Profiles {
    int32_t param1;
    int32_t param2;
    int32_t param3;
    int32_t param4;
    int32_t param5;
    int16_t param6;
    int32_t param7;
    uint32_t param8;
    int32_t param9;
    int32_t param10;
    uint32_t param11;
    int32_t time;
/* @@protoc_insertion_point(struct:Profiles) */
} Profiles;

The expected result would be that I can store a logged line like the following: 5 1345643 1500 (tag, time, value)预期的结果是我可以存储如下记录的行:5 1345643 1500 (tag, time, value)

to a protocol buffer struct:到协议缓冲区结构:

profiles.param5 = 1500
profiles.time  = 1345643 

without the need of 12 switch cases (in this example).无需 12 个开关盒(在此示例中)。 Basically, how can I access the 5th declared field of a struct using an integer/enum.基本上,如何使用整数/枚举访问结构的第 5 个声明字段。

Bare in mind that each field of the struct could potentially have a different type.请记住,结构的每个字段都可能具有不同的类型。

My approach would be having pointers to each of the fields as below.我的方法是指向每个字段,如下所示。

int *ptr[11] = {&profiles.param1, &profiles.param2,  &profiles.param3,,,,,, &profiles.param11};

And when the message arrives, I will update the field using ptr .当消息到达时,我将使用ptr更新该字段。

  *ptr[tag-1] = 1500; //tag-1 because ptr[4] points to profiles.param5

Improving on the previous solution by @kiran.改进@kiran 之前的解决方案。

In case you have multiple types then you need to store void pointers.如果您有多种类型,则需要存储 void 指针。 But for typecasting you again need to have a switch case.但是对于类型转换,您再次需要一个开关盒。

This can be avoided in two ways.这可以通过两种方式避免。

  1. Store the type along with the data.将类型与数据一起存储。 ie, store (tag, type, time, value) .即,存储(tag, type, time, value) Then you can have a limited no of conditions for the types.然后,您可以对这些类型设置有限的条件。

     void *ptr[11] = {&profiles.param1, &profiles.param2, &profiles.param3,,,,,, &profiles.param11}; switch (type) { case 0: *(char*)ptr[tag-1] = value; break; case 1: *(int*)ptr[tag-1] = value; break; ... }
  2. Alternatively you can have a map which stores the type of the value或者,您可以使用 map 存储值的类型

    void *ptr[11] = {&profiles.param1, &profiles.param2, &profiles.param3,,,,,, &profiles.param11}; char typearr[11] = {0,1,0,0....1}; // 0 for char, 1 for int etc type = typearr[tag-1]; switch (type) {... }

I think the answer is about Reflection.我认为答案是关于反射的。 C language does not have support for reflection. C 语言不支持反射。 High level languages like C# have this support. C# 等高级语言具有此支持。 Please take look at this example;请看这个例子;

PropertyInfo.SetValue Method PropertyInfo.SetValue 方法

Hope it helps.希望能帮助到你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM