在充满向量计算的代码中使用以下预处理器技巧是一种好习惯吗?一方面,它使用通用标识符(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);
}
答案 0 :(得分:3)
不,这不是一个好主意(当然,我认为)。
假设我比较熟悉C语言,如果我看到一行代码如下:
d = vector_mul(vector_add(a,b),c);
我很清楚它的作用。我需要查看a
,b
,c
和d
的类型以及函数的声明,但即使没有我可以安全地假设它正在进行向量加法和向量乘法。
另一方面,如果我看到:
d = _( _(a add b) mul c);
在我第一次追踪宏定义之前,我可能不知道它在做什么,然后研究它们直到我理解你的新语法,或者只是将它们扩展到我能理解的普通C代码。当然你知道你的语法意味着什么,如果你是唯一一个阅读代码的人,那就没问题了,但是其他人都会想知道下划线的含义。
这是假设我意识到你正在使用宏。宏名称通常用全大写字母书写。使用ADD
和MUL
会有所改进,但恕我直言还不足以超越其他缺点。
个人轶事:很多年前,当我第一次学习C时,我认为这是:
#define EVER ;;
...
for (EVER) {
/* ... */
}
非常聪明。我仍然认为这很聪明;我不再认为这是个好主意。