0

我有一些包含数组的结构

struct mystruct_withArrays {
  int foo;
  int bar[MaxN];
  int baz[MaxM];
}

以及它们与指针的等价物

struct mystruct_withPointers {
   int foo;
   int *bar;
   int *baz;
}

想避免双重定义。这是我想做一些东西作为模板

#define myStruct(M,N)
...

这样myStruct(MaxM,MaxN)生成数组结构并myStruct(,)生成带有指针的结构。

此外,我当然想对多个结构执行相同的技术,并实现从数组到指针的自动映射。最终用例可能如下

#include "mystructs.h"

//globals, for huge space usage

struct myStructA(1000,10000) hugeA;

struct myStructB(1024*1024) * hugeB;

void main(){


struct myStructA(,) smallA;
struct myStructB() smallB;


mapStruct(hugeA,smallA) //this is a macro
mapStruct(hugeB,smallB) //this is a macro

doSomething(smallA);
doSomethingMore(smallA,smallB);
doSomethingDetailed(smallB.qux);
}

哪里mapStruct(hugeA, smallA)是明显的映射smallA.bar = hugeA.bar等。扩展的代码将是:

struct myStructA(1000,10000) hugeA;
struct myStructB(1024*1024) hugeB;

struct mystructA_withArrays {
  int foo;
  int bar[1000];
  int baz[10000];
} hugeA;

struct mystructB_withArrays * {
  int qux[1048576];
  int quux[1048576];
} hugeB;


void main(){


struct mystructA_withPointers {
  int foo;
  int * bar;
  int * baz;
} smallA;

struct mystructB_withArrays {
  int * qux;
  int * quxx;
} smallB;

smallA.bar=hugeA.bar;
smallA.baz=hugeA.baz;
smallB.qux=hugeB.qux;
smallB.quxx=hugeB.quxx;

doSomething(smallA);
doSomethingMore(smallA,smallB);
doSomethingDetailed(smallB.qux);

}

如您所见,一般的想法是一些变量分配在堆栈之外,但仍然没有使用malloc,只是将它们声明为全局变量。即使在某些用例中,它们也是来自链接共享对象的外部全局变量。

编辑:关于内存性能,很难确定 malloc 结构比全局结构好还是差。它还取决于编译器的标志 -mcmodel

4

2 回答 2

2

明智的KISS解决方案似乎是这样的:

struct mystruct {
   int foo;
   int *bar;
   int *baz;
};

struct mystruct array = 
{ 
  .bar = (int[ 1000]){0},
  .baz = (int[10000]){0},
};

struct mystruct pointers;

现在无论数据如何分配,这个结构的接口都是一样的,“数组结构”与“指针结构”100%兼容。如果在文件范围内声明,复合字面量的分配将以 结束.bss,与伪代码中的处理相同。

于 2022-01-14T09:18:03.967 回答
1

创建几个类似结构的可能解决方案可能是使用X 宏。(与 Wikipedia 页面不同,我将宏X作为参数传递,而不是重新定义宏。)

我稍微编辑了代码以将数组的分配添加到相应的指针。我使用可变参数宏来允许省略参数列表中的变量名。这是为了展示概念,可能还有改进的余地。

示例文件macro.c

#define LIST_OF_ARRAY_FIELDS_1(X, ...) \
    X(int, bar, MaxN, __VA_ARGS__) \
    X(int, baz, MaxM, __VA_ARGS__)

#define LIST_OF_ARRAY_FIELDS_2(X, ...) \
    X(char, bla1, MaxK, __VA_ARGS__) \
    X(char, bla2, MaxL, __VA_ARGS__)

#define CREATE_ARRAY_FIELD(type, name, size, ...) \
    type name[size];

#define CREATE_POINTER_FIELD(type, name, size, ...) \
    type *name;

struct mystruct_withArrays {
    int foo;
    LIST_OF_ARRAY_FIELDS_1(CREATE_ARRAY_FIELD)
}

struct mystruct_withPointers {
    int foo;
    LIST_OF_ARRAY_FIELDS_1(CREATE_POINTER_FIELD)
}

struct otherstruct_withArrays {
    int foo;
    LIST_OF_ARRAY_FIELDS_2(CREATE_ARRAY_FIELD)
}

struct otherstruct_withPointers {
    int foo;
    LIST_OF_ARRAY_FIELDS_2(CREATE_POINTER_FIELD)
}

mystruct_withArrays hugeA;
mystruct_withPointers smallA;

otherstruct_withArrays hugeB;
otherstruct_withPointers smallB;

#define ASSIGN_POINTERS(type, name, size, dest, src) \
    dest.name = src.name;

LIST_OF_ARRAY_FIELDS_1(ASSIGN_POINTERS, smallA, hugeA)

LIST_OF_ARRAY_FIELDS_2(ASSIGN_POINTERS, smallB, hugeB)

结果:

$ gcc -E macro.c
# 1 "macro.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "macro.c"
# 15 "macro.c"
struct mystruct_withArrays {
    int foo;
    int bar[MaxN]; int baz[MaxM];
}

struct mystruct_withPointers {
    int foo;
    int *bar; int *baz;
}

struct otherstruct_withArrays {
    int foo;
    char bla1[MaxK]; char bla2[MaxL];
}

struct otherstruct_withPointers {
    int foo;
    char *bla1; char *bla2;
}

mystruct_withArrays hugeA;
mystruct_withPointers smallA;

otherstruct_withArrays hugeB;
otherstruct_withPointers smallB;




smallA.bar = hugeA.bar; smallA.baz = hugeA.baz;

smallB.bla1 = hugeB.bla1; smallB.bla2 = hugeB.bla2;

于 2022-01-13T14:24:33.173 回答