运算符使用预处理器重载C语法

时间:2012-09-27 20:54:47

标签: c operator-overloading c-preprocessor

在充满向量计算的代码中使用以下预处理器技巧是一种好习惯吗?一方面,它使用通用标识符(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);
}

1 个答案:

答案 0 :(得分:3)

不,这不是一个好主意(当然,我认为)。

假设我比较熟悉C语言,如果我看到一行代码如下:

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

我很清楚它的作用。我需要查看abcd的类型以及函数的声明,但即使没有我可以安全地假设它正在进行向量加法和向量乘法。

另一方面,如果我看到:

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

在我第一次追踪宏定义之前,我可能不知道它在做什么,然后研究它们直到我理解你的新语法,或者只是将它们扩展到我能理解的普通C代码。当然知道你的语法意味着什么,如果你是唯一一个阅读代码的人,那就没问题了,但是其他人都会想知道下划线的含义。

这是假设我意识到你正在使用宏。宏名称通常用全大写字母书写。使用ADDMUL会有所改进,但恕我直言还不足以超越其他缺点。

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

#define EVER ;;

...

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

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