3

在充满矢量计算的代码中使用以下预处理器技巧是一个好习惯吗?一方面,它使用通用标识符(mul,add,...)污染了命名空间,闻起来像一个肮脏的黑客,但另一方面,它可能使复杂的表达式更具可读性。还有其他优点/缺点吗?

typedef struct { double x,y; } vector;
vector vector_add(vector v0, vector v1);
double vector_mul(vector v0, vector v1);
...
#define _(a) opf(a)
#define mul ,mul,
#define add ,add,
...
#define opf(a,o,b) vector_##o((a),(b))

void example(void)
{
  vector a, b, c;
  double d;

  d = _( _(a add b) mul c);

  // equivalent without the macros:
  d = vector_mul(vector_add(a,b),c);
}
4

1 回答 1

3

不,这不是一个好主意(当然,在我看来)。

假设我相当了解 C 语言,如果我看到如下代码行:

d = vector_mul(vector_add(a,b),c);

我很清楚它的作用。可以肯定的是,我需要查看 、 、 和 的类型a以及b函数cd声明,但即使没有这些,我也可以放心地假设它正在执行向量加法和向量乘法。

另一方面,如果我看到:

d = _( _(a add b) mul c);

在我首先追踪宏定义之前,我可能不知道它在做什么,然后要么研究它们直到我理解你的新语法,要么自己将它们扩展为我能理解的普通 C 代码。当然知道你的语法是什么意思,如果你是唯一阅读代码的人,那很好,但其他人会想知道下划线是干什么用的。

这是假设我意识到您正在使用宏。宏名称通常以全大写形式书写。使用ADDandMUL将是一个改进,但恕我直言,不足以覆盖其他缺点。

个人轶事:很多年前,当我第一次学习 C 时,我认为是这样的:

#define EVER ;;

...

for (EVER) {
    /* ... */
}

很聪明。我仍然认为它非常聪明;我只是不再认为这是一个好主意。

于 2012-09-27T22:33:28.147 回答