我什么时候可以省略C中的花括号?

我几乎肯定以前曾经问过这个问题,但我发现它无法在任何地方得到解答。

我什么时候可以省略C中的花括号? 我以前见过无支撑return语句,例如

 if (condition) return 5; 

但这似乎并不总是适用于所有语句,即在声明方法时。

编辑

大括号遗漏的规则是否与Java相同?

如果正文由单个语句组成, while可以省略括号的唯一位置是if-elseforwhiledo-while语句的主体:

 if (cond) do_something(); for (;;) do_something(); while(condition) do_something(); do do_something(); while(condition); 

但是,请注意,上述每个示例都根据语法计为单个语句; 这意味着你可以写出类似的东西

 if (cond1) if (cond2) do_something(); 

这是完全合法的; if (cond2) do_something(); 简化为单一陈述。 那么,就此而言, if (cond1) if (cond2) do_something(); 所以你可以用类似的东西进一步陷入疯狂

 for (i=0; i < N; i++) if (cond1) if (cond2) while (cond3) for (j=0; j < M; j++) do_something(); 

不要那样做。

如果你看一下C语法,有许多上下文需要一个语句 ,一个由语法本身定义的术语。

在任何这些上下文中,您可以使用的一种语句forms是复合语句 ,它由一个左括号{ ,一个零或多个声明和/或语句的序列,以及一个右括号} 。 (在C90中,复合语句中的所有声明必须在所有语句之前; C99删除了该限制。)

函数定义特别需要复合语句 ,而不仅仅是任何类型的语句。 (我认为这是唯一一种复合语句是你可以使用的唯一语句的情况)。 如果没有这个限制,你可以写:

 void say_hello(void) printf("Hello, world\n"); 

但由于大多数函数定义包含多个声明和/或语句,因此在允许的情况下没有太大的优势。

还有一个单独的问题:什么时候应该省略大括号。 在我个人看来,答案是“几乎没有”。 这个:

 if (condition) statement; 

是完全合法的,但这个:

 if (condition) { statement; } 

恕我直言阅读更好,更容易维护(如果我想添加第二个声明,大括号已经存在)。 这是我从Perl那里学到的习惯,在所有这些情况下都需要括号。

我将省略大括号的唯一一次是当一个完整的if语句或类似的东西适合单行时,这样做会使代码更易于阅读, 而且我不太可能想要为每个语句添加更多语句:

 if (cond1) puts("cond1"); if (cond2) puts("cond2"); if (cond3) puts("cond3"); /* ... */ 

我发现这种情况相当罕见。 即便如此,我仍然会考虑添加大括号:

 if (cond1) { puts("cond1"); } if (cond2) { puts("cond2"); } if (cond3) { puts("cond3"); } /* ... */ 

但这似乎并不总是适用于所有陈述。

特别? 当预期单个语句时,它就完全有效。 所有循环, if语句等等都需要一个语句,这或者是一个块,或者说是一个单独的语句,而不是被包含在一个块中。

一个例子:

 int a[2][2] = {{1, 2}, {3, 4}}; 

您可以使用有效的等效表格:

 int a[2][2] = {1, 2, 3, 4}; 

一些冗长的编译器可能会发出警告,但它是有效的。

请注意,对于if语句( whilefor语句,…), {}不会被省略。 他们只是没有要求。 if语句具有以下语法:

if (expression) statement

如果您想要多个语句而不是单个语句,则可以使用包含{}的复合语句。

当您想要将多个语句或表达式合并为一个时,您主要需要大括号,例如:

 { x = 1; y = 2; } 

因此,如果你将上面的if放在if下if else括号中的整个东西将作为一个整体执行,而如果你省略大括号,只有第一个( x = 1;在这种情况下)将被用作if一部分或者。

您通常也会将它们与switch()

 switch (x) { case 1: // do smth break; case 2: // do smth else break; } 

您通常需要使用do-while语句:

 do { printf("%d\n", x); x++; } while (x < 10); 

当您想在代码中间定义和使用临时变量时,需要使用C89编译器:

 int main(void) { puts("Hello World!"); { int x; for (x = 0; x < 10; x++) printf("%d\n", x); } return 0; } 

您可以使用它们来开始和结束函数体,结构/联合定义,枚举定义,结构/联合/数组的初始化,例如:

 void blah(void) { } enum e { e1 = 1, e2 = 2 }; struct s { int foo; int bar; } s = { 1, 2 }; int a[3] = { 1, 2, 3 }; 

您可以在初始化时省略它们,例如:

 char str2[] = { "abc" }; char str1[] = "abc"; 

任何时候都有一个包含多行的块(将行计数为带有;的单个语句;)

例子:

 for (i = 0; i < j; i++ ) foo(i); while (1) foo(); if( bool ) foo(); void cheese() printf("CHEESE"); 

之后的一切; 在上面的行中不计算块的“内部”,就好像有{}。

当您正在执行单个语句时,可以省略它们:

 for(...) printf("brackets can be omited here"); if(...) printf("brackets can be omited here"); else printf("brackets can be omited here too"); 

等等。你可以随时添加它们,它永远不会伤害并有助于澄清范围,但你很安全。 我能想到的唯一“捕获”是你试图在那个范围内做出声明(顺便说一句,这是无用的):

 if(...) int a = 5; 

这将导致错误,但这是因为您可以执行单个语句而不使用大括号,而不是声明 。 重要的区别。

从技术上讲,如果它们与操作员连接,你甚至可以进行多个没有括号的操作……不是我建议这样做,只是值得注意:

 if(...) value++, printf("updated value with brackets"); 

对于您的编辑,您可以在java规范中看到规则是相同的。 我特意链接到if部分,但你可以在if之后看到一个声明,因此你可以跳过大括号。

如有疑问,请使用牙箍。 它们不会“花费”任何额外费用[除非你绝对错误地使用它们]。

一个相当基本的规则是“如果你在同一个缩进处有一个以上的分号,你应该有大括号”。 这不是那么简单,但作为一个“没有ifs,buts或其他并发症的一句话”,它将不得不做。

是的,基于C语法的Java具有相同的基本规则 – 可能有一些奇怪的地方,Java与C或C ++不同,但这是不寻常/奇怪的事情,而不是你在编写典型代码时通常会遇到的事情[I没有做太多的java,所以我不能说我找到了他们中的任何一个,但我很确定会有一些差异 – 毕竟他们是不同的语言。

以下似乎有点棘手:

 if (...) printf("I'm conditional\n"); 

我猜C预处理器会处理空行,所以这句话很好。 当然非常糟糕的做法。