删除 "if" 语句的大括号是否有任何例外?

Are there any exceptions in removing curly braces for an "if" statement?

我是一名计算机科学专业的学生,​​前段时间我们的教授向我们解释说,在 C 语言中,当只有一个语句时,我们可以删除花括号:

if (a)
  do b

但我们不能这样做:

if(a)
  do b
  do c

因为那会做不止一个声明。

但它也告诉我们,删除花括号是一个例外,即使它只是一个语句我们也做不到。我做了很多搜索,但我唯一发现的是我不能在 do-while 循环中这样做,但我们正在谈论 if 语句,有帮助吗?

编辑:我们还讨论了嵌套的 if 语句,也许是关于那个?

你教授说的可能是这样的情况:

if (a)
    if (b)
        printf("a and b\n");
else  // this goes with the inner "if"
    printf("not a\n");

与缩进所暗示的相反,else 与外部 if 语句无关,但与内部 if 语句相关联。在这种情况下,您需要将花括号添加到外部 if 的主体,以便 else 正确关联:

if (a) {
    if (b)
        printf("a and b\n");
}
else
    printf("not a\n");

最好始终对条件和循环结构的主体使用大括号,以防止这种歧义和随之而来的错误。

好吧,总是可以使用不带大括号的单个语句。但是,如果您没有 any 语句怎么办:

if (ham)
    int eggs = spam();

无法编译,因为 if 需要准确地保护 one 语句。

if (ham) {
    int eggs = spam();
}

确实如此。有一个复合语句,其声明带有调用函数的初始化;和 0 个陈述。当然这并不是真的有用,因为变量在其他情况下未被使用...

But it also told us that there's an exception about removing curly braces, something we can't do even if it's only one statement.

我相信你的教授正在努力教你最佳实践。尽管就 C 语言而言,我们 可以 编写 if 没有花括号的语句,但我们永远不应该这样做。这并不是主观的个人风格偏好,而是程序安全问题。

因为很容易写出这样的bug:

if ((err = SSLHashSHA1.update(&hashCtx, &signedParams)) != 0)
    goto fail;
    goto fail;  /* MISTAKE! THIS LINE SHOULD NOT BE HERE */

第 2 个 goto 将始终执行,这不是故意的。我敢说每一个允许这种风格的 C 程序员也写过这个错误。在我完全停止使用这种风格之前,我确实偶尔会这样做。

出于这个安全原因,著名的编码标准(例如 CERT-C 和 MISRA-C)禁止使用 if 等不带大括号的代码。请参阅 CERT-C EXP19-C 和 MISRA-C:2012 规则 15.6。

使用这种语法的宏(多行)很难调试。您必须查看经过预处理的 C 代码才能确定问题所在。

#define MULTISTATEMENT a=5;\
                       b=5;
#include <stdio.h>

int main() {
   int a = 10, b = 10;
   if(a == 10)
       MULTISTATEMENT
   else
       a = 3;
   printf("a = %d b = %d\n", a, b);
   return 0;
}

此代码产生错误。将 {} 放在宏周围或 if 语句周围以编译此代码。