如何使用预处理器缩短这些行?

How to shorten these lines using preprocessor?

我的代码中有这些行,我想可能有一些很好的方法可以使用预处理器生成这些行(0 到 31)。

    Mem_type MEM_0[MAX_NUM_MEM];
    Mem_type MEM_1[MAX_NUM_MEM];
    Mem_type MEM_2[MAX_NUM_MEM];
    Mem_type MEM_3[MAX_NUM_MEM];
    Mem_type MEM_4[MAX_NUM_MEM];
    Mem_type MEM_5[MAX_NUM_MEM];
    ...
    Mem_type MEM_30[MAX_NUM_MEM];
    Mem_type MEM_31[MAX_NUM_MEM];

    Mem_type *MEM[NUM_BANKS];

    MEM[0] = MEM_0;
    MEM[1] = MEM_1;
    MEM[2] = MEM_2;
    MEM[3] = MEM_3;
    MEM[4] = MEM_4;
    MEM[5] = MEM_5;
    ...
    MEM[30] = MEM_30;
    MEM[31] = MEM_31;

例如:

    #define Gen(n) MEM[n] = MEM_n
    #for (k=0; k<32; k++) Gen(k);

(我不喜欢下面的原因是我发现我的机器有一些最大的连续数组大小限制,所以我试图把它分成单独的数组,这样我就可以有更大的聚合内存大小.)

    Mem_type MEM[NUM_BANKS][MAX_NUM_MEM];

网上有关于预处理阶段的符号计算的文章,一个典型的例子是http://jhnet.co.uk/articles/cpp_magic

如果定义的机制对您来说太多了,并且您不太关心生成代码的美观性,您可以使用便宜的替代方案,例如(未测试):

#define ONE_MEM(i, a) MemType mem_ ## a[MAX_MEM]; mem[i] = mem_ ## a
#define MEM_1(i, a) ONE_MEM(i, a); ONE_MEM(i + 1, a ## 1)
#define MEM_2(i, a) MEM_1(i, a); MEM_1(i + 2, a##2)
#define MEM_4(i, a) MEM_2(i, a); MEM_2(i + 4, a##4)

依此类推,现在定义的宏数量是对数的。

(尚未测试,实际定义可能需要一两个 concat 间接寻址。)

可以进行改进,比如声明一个宏参数来替代 mem

使用 boost/preprocessor/repetition/repeat.hpp :

#include <boost/preprocessor/repetition/repeat.hpp>
class Mem_type {};

#define MAX_NUM_MEM  5
#define NUM_BANKS    5

#define MEM_DECL(z, n, text)  Mem_type MEM_## n[MAX_NUM_MEM];
#define MEM_MEMB(z, n, text)  MEM_## n,

// expands to `Mem_type MEM_?[MAX_NUM_MEM];`
BOOST_PP_REPEAT(NUM_BANKS, MEM_DECL, ())

Mem_type *MEM[NUM_BANKS] = {
    // expands to `MEM_?,`
    BOOST_PP_REPEAT(NUM_BANKS, MEM_MEMB, ())
};

堆栈非常有限,不应该用于分配像这样的巨大数据结构,如讨论的那样here. Instead try to allocate your memory using new[]. If you do need multidimensional arrays you can use an array of pointers that point to arrays pointing to your structures as described here

然而,由于您的最初意图是拥有一个数组,因此无需预处理器即可实现此目的:

Mem_type* MEM = new Mem_type[MAX_NUM_MEM]; // MAX_NUM_MEM is multiplied by NUM_BANKS here
// do things [...]
delete[] MEM;
MEM = nullptr;

最好将其包装在 class 中,在构造函数中分配,如果分配失败则抛出异常并在析构函数中解除分配。

对 STL 向量使用动态分配:

#include <vector>

class Mem_type {};
const int MAX_NUM_MEM = 5;
const int NUM_BANKS   = 5;

// allocates NUM_BANKS vectors with MAX_NUM_MEM objects of Mem_type
std::vector<std::vector<Mem_type>> MEM(NUM_BANKS, std::vector<Mem_type>(MAX_NUM_MEM));

您可以将 X Macro 与令牌连接一起使用

#define LIST_OF_MEMS    \
X(0)                    \   
X(1)                    \
X(2)                    \
X(3)                    \
X(4)                    \
X(5)                    \
...                     \
X(30)                   \
X(31)                   \

现在您可以在每次想要对所有 MEM 执行任何操作时使用它。请注意,对变量名使用全部大写是个坏主意

// declaration
#define X(num) Mem_type mem_##num[MAX_NUM_MEM];
LIST_OF_MEMS
#undef X

// assignment
#define X(num) MEM[num] = mem_##num;
LIST_OF_MEMS
#undef X