for循环宏编码风格

时间:2016-12-11 19:55:10

标签: c loops macros c-preprocessor

我在大学的一位导师建议使用宏来减少c99代码中的重复,就像这样。

#define foreach(a, b, c) for (int a = b; a < c; a++)
#define for_i foreach(i, 0, n)
#define for_j foreach(j, 0, n)
#define for_ij for_i for_j

可以这样使用:

for_ij { /*do stuff*/; }
for_i  { /*do stuff*/; }

另一位具有工业背景的导师不鼓励使用它,声称它被视为他前任雇主的反模式(但他不知道背后的原因)。实际上,通过浏览大型项目的源代码,很少能够在简短的学术范例之外找到这些结构。

我的问题是:为什么这种结构在实践中很少使用?它在某种程度上是危险的吗?

2 个答案:

答案 0 :(得分:8)

这是学术界和现实世界之间差距的完美例证,很难相信。但是看起来太奇怪了。

回答你的问题:这种结构在实践中使用,因为它使用隐式变量和条件隐藏信息,所以存在风险。

以下是随意读者会思考的一些问题:

  • 上限是多少?它不应该是n
  • i的实际范围是什么?
  • 基于0
  • 包括n还是之前停止?

C程序员非常擅长阅读惯用语结构,例如

for (int i = 0; i < n; i++) {
    ...
}

隐藏此循环逻辑的详细信息不会产生任何影响,适得其反,容易出错,并且应该被本地编码约定禁止。它不在我的团队中的唯一原因是没有人想出这么奇怪的想法。

您可能需要谨慎使用希望使用这些缩写的大学导师,可能是APL怀旧,并避免冲突。你可能想跟他玩一些code golfing,有一个stack exchange dedicated to that,他会喜欢人们浪费无数小时从他们的源代码中删除字节......

但是你应该遵循其他导师的建议,编写清晰明确的代码,仔细缩进和间隔,重要的是有意义的名字,而使用很明显的短名称。尽可能使用惯用结构,因为它使代码更易读,更不容易出错,更适合优化编译器。

答案 1 :(得分:3)

问题在于重复的减少(以及可读性的提高)相当微不足道。你正在减少

for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++)

for_ij
由于变量名称ijn都很短,因此重复它们不是问题,因此

没有太大改进。

与此同时,您隐藏了参数n - 后一个循环隐含地依赖于n,即使n无法在for_ij中出现或者(很可能)在for循环的主体中。隐藏重要信息会使阅读代码变得更加困难 - 为了阅读本文,您需要了解n的重要性,您只能通过搜索两个级别的宏间接来看到它。