【问题标题】:Astyle with --remove-brackets and a macro带有 --remove-brackets 和宏的 Astyle
【发布时间】:2014-12-27 18:54:09
【问题描述】:

附上代码:

#define MACRO(A,B) foo(A); bar(B)

if(true) {
    MACRO(A,B);
}

Astyle 将删除宏调用周围的括号

if(true)
    MACRO(A,B);

幸运的是,我找到了解决方案。如果我将; 放在宏中,Astyle 会理解它。

#define MACRO(A,B) foo(A); bar(B);

if(true) {
    MACRO(A,B)
}

这是一个好的解决方案,是Astyle的一个错误还是我的误解?

【问题讨论】:

  • 宏开始时这种风格非常糟糕。它可能应该使用do { ... } while(false) 模式(没有最终的;)。
  • 去掉括号也是一种可疑的风格...
  • @DevSolar:用过多的括号、比较、换行符……
  • @Deduplicator:我记得我们已经在另一个评论线程中对这个问题产生了分歧。远离我的消息来源好吗?
  • @DevSolar:我从未更改过您的代码(我记得)。无论如何,新代码应该始终遵循现有代码库已经使用的任何样式。但如果你说它的风格不好/可疑,那你就是在要求矛盾。

标签: c astyle


【解决方案1】:

由于多种原因,类似函数的宏总是不好的风格。类型安全性差、难以阅读、难以调试/维护、极易出错、使程序面临各种定义不明确的行为等等。

没有大括号的控制或循环语句是危险的风格,因为它使程序容易受到许多难以置信的常见错误的影响。有些人会争辩说“没有大括号使代码更具可读性”(我自己曾经参加过这个阵营),然后他们会因此而跳过编写错误。没有花括号总是迟早会导致错误。

如果你总是使用大括号,那么你在编写宏时就不需要使用各种晦涩的技巧了。

风格不错:

void function (type A, type B)
{
  foo(A);
  bar(b)
}

if(true) 
{
  function(A, B);
}

【讨论】:

  • 真的想在这里发起一场风格大战?
  • 如果您只针对 GCC,我不会说类似函数的宏不好。例如,typeof 扩展和语句表达式允许您编写类型通用的 MAX 宏。
  • @Deduplicator 这不是风格,这是一种糟糕且危险的做法。非我个人主观意见,可以参考MISRA-C等编程权威。它是一个只关注程序安全的文档,对编码风格没有任何限制。然而,出于安全原因,它禁止使用类似函数的宏并且禁止不带大括号的控制语句。这反过来又间接地基于实际的科学研究:已经对源代码进行了人口研究,以确定软件缺陷的常见原因。请参阅 MISRA-C:2012 指令 4.9 和规则 15.6。
  • @coin 首先,函数调用开销在 99% 的情况下都不是问题。请注意,我主要编写性能关键的实时嵌入式系统,而函数调用开销在那些中很少成为问题。无论如何,您所说的是过早的优化,就像在 90 年代初所做的那样。现代编译器使用函数内联并且通常能够在没有提供 inline 关键字的情况下这样做。在现代编译器上的现代编程中,永远不要为了性能而用宏替换函数。
  • @coin 汇编器无法优化,因此您无法真正将其与 C 进行比较。汇编器程序员必须手动进行 all 优化。并且 1 MB 的 RAM 是内存的海洋 :)
【解决方案2】:

这是一种糟糕的风格。

如果您绝对必须在宏中包含多个语句,请将它们包装在 do while 循环中(注意末尾缺少分号):

#define MACRO(A,B) do { foo(A); bar(B); } while(0) 

【讨论】:

  • 或者更好的是,您可以将语句表达式与支持它们的编译器一起使用。您可以获得额外的好处,即您的宏可以返回一个类似于“真实”函数的值。
  • 顺便说一句:在这种情况下,逗号运算符有效:(foo(A),bar(B))
  • @Deduplicator:是的,但考虑必须在块中使用任何临时变量。
  • @BlagovestBuyukliev:我说,“在这种情况下”。当然,一些/许多/大多数其他情况有所不同。
猜你喜欢
  • 1970-01-01
  • 2017-12-02
  • 1970-01-01
  • 1970-01-01
  • 2013-06-03
  • 2013-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多