在 C 中用宏处理双变量 switch 语句

Handling double-variable switch statement with macro in C

假设我有两个指向两个结构 ab 的指针。这两个结构各自包含一个枚举,我们称之为 x。给定任何可能的 ab,我想根据它们的 x 枚举的值调用特定函数。 在我的案例中有趣的是我想调用的函数如下所示:

X0_to_X1();
X0_to_X2();
...
X1_to_X0();
...
etc

其中 X0X1 等是枚举 x 的可能值,这意味着对于每个值的每个组合都有 X_to_Y 个函数x枚举。

明显的“天真”解决方案是一个相当大的 switch 语句(假设 x 有很多可能的值):

switch (a->x) {
    case X0:
        switch (b->x) {
            case X1:
                X0_to_X1();
                break;

// ... and so on and so forth for every possible pair!

我第一次尝试更优雅地解决这个问题是实现一个宏,给定 x 的两个值,可以形成一个函数调用:

#define CALL_FUNCTION(x1, x2) x1 ## _to_ ## x2 ()

但是这不起作用,因为在我的代码中我永远无法在运行前知道 x 实际 值,所以它最终看起来像:

CALL_FUNCTION(a->x, b->x);

当然会转换为:

a->x_to_b->x();

这完全没有意义。

有没有办法更优雅地解决这个问题,还是我应该硬着头皮实现巨大的 switch 语句?

这个问题急需查找 table,您在其中存储指向各种函数的指针,它们由枚举值作为键。

如果您的 enum 值是连续的(并且没有两个枚举常量共享相同的值),那么您可以构建一个查找 table 作为一个简单的二维数组:

enum x_t { X0, X1, X2, ..., NUM_X }; 
void (*lookup[NUM_X][NUM_X])(void) = {
  { NULL, X0_to_X1, X0_to_X2, X0_to_X3, ... },
  { X1_to_X0, NULL, X1_to_X2, X1_to_X3, ... },
  { X2_to_X0, X2_to_X1, NULL, X2_to_X3, ... },
  ...
};

当您的 xy 相同时,假设您没有“身份”功能。

然后,您通过索引到 table 来调用所需的函数,如下所示:

if ( x != y )
  lookup[x][y]();

不,它不漂亮,但它胜过嵌套的 switch 语句。如果愿意,您可以将其隐藏在宏或其他函数调用后面。

如果您的枚举值不是连续的,那么这个特定的实现将不起作用 - 您必须使用列表或稀疏矩阵以不同的方式构建查找 table。但是虽然设置代码可能很繁琐,但它会大大简化调用方的逻辑。