gpt4 book ai didi

c - 从 C 中的大结构中获取子结构

转载 作者:太空狗 更新时间:2023-10-29 15:45:40 25 4
gpt4 key购买 nike

我在现有程序中有一个非常大的struct。该结构包含大量位域。

我希望保存其中的一部分(例如,150 个字段中的 10 个)。

我将用来保存子类的示例代码是:

typedef struct {int a;int b;char c} bigstruct;
typedef struct {int a;char c;} smallstruct;
void substruct(smallstruct *s,bigstruct *b) {
s->a = b->a;
s->c = b->c;
}
int save_struct(bigstruct *bs) {
smallstruct s;
substruct(&s,bs);
save_struct(s);
}

我也希望选择它的哪一部分不会太麻烦,因为我希望不时更改它。我之前提出的幼稚方法非常脆弱且无法维护。当扩展到 20 个不同的字段时,您必须更改 smallstructsubstruct 函数中的字段。

我想到了两种更好的方法。不幸的是,两者都需要我使用一些外部 CIL就像解析我的结构的工具。

第一种方法是自动生成substruct 函数。我将设置 smallstruct 的结构,并有一个程序可以解析它并根据 smallstruct 中的字段生成 substruct 函数.

第二种方法是构建(使用 C 解析器)有关 bigstruct 的元信息,然后编写一个允许我访问结构中特定字段的库。这就像 Java 类反射的临时实现。

例如,假设没有结构对齐,对于结构

struct st {
int a;
char c1:5;
char c2:3;
long d;
}

我将生成以下元信息:

int field2distance[] = {0,sizeof(int),sizeof(int),sizeof(int)+sizeof(char)}
int field2size[] = {sizeof(int),1,1,sizeof(long)}
int field2bitmask[] = {0,0x1F,0xE0,0};
char *fieldNames[] = {"a","c1","c2","d"};

我将使用此函数获取ith 字段:

long getFieldData(void *strct,int i) {
int distance = field2distance[i];
int size = field2size[i];
int bitmask = field2bitmask[i];
void *ptr = ((char *)strct + distance);
long result;
switch (size) {
case 1: //char
result = *(char*)ptr;
break;
case 2: //short
result = *(short*)ptr;
...
}
if (bitmask == 0) return result;
return (result & bitmask) >> num_of_trailing_zeros(bitmask);
}

这两种方法都需要额外的工作,但是一旦解析器在您的 makefile 中 - 更改子结构就轻而易举了。

但是我宁愿在没有任何外部依赖的情况下这样做。

有没有人有更好的主意?我的想法有什么好的地方,是否可以在互联网上实现我的想法?

最佳答案

从您的描述来看,您似乎可以访问并可以修改您的原始结构。我建议您将子结构重构为一个完整的类型(就像您在示例中所做的那样),然后将该结构作为大结构中的一个字段,将原始结构中的所有这些字段封装到较小的结构中。

扩展你的小例子:

typedef struct 
{
int a;
char c;
} smallstruct;

typedef struct
{
int b;
smallstruct mysub;
} bigstruct;

访问 smallstruct 信息将像这样完成:

/* stack-based allocation */
bigstruct mybig;
mybig.mysub.a = 1;
mybig.mysub.c = '1';
mybig.b = 2;

/* heap-based allocation */
bigstruct * mybig = (bigstruct *)malloc(sizeof(bigstruct));
mybig->mysub.a = 1;
mybig->mysub.c = '1';
mybig->b = 2;

但您也可以传递指向小结构的指针:

void dosomething(smallstruct * small)
{
small->a = 3;
small->c = '3';
}

/* stack based */
dosomething(&(mybig.mysub));

/* heap based */
dosomething(&((*mybig).mysub));

好处:

  • 没有宏
  • 无外部依赖
  • 没有内存顺序转换技巧
  • 更简洁、更易于阅读和使用的代码。

关于c - 从 C 中的大结构中获取子结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/882956/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com