22

我几乎可以肯定以前有人问过这个问题,但我在任何地方都找不到答案。

我什么时候可以在 C 中省略花括号?我以前看过无括号的return陈述,例如

if (condition)
  return 5;

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

编辑

大括号省略的规则与 Java 中的规则相同吗?

4

10 回答 10

21

唯一可以省略括号的地方是if-else, for, while, 或do-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(); 

不要那样做。

于 2013-02-15T21:39:06.997 回答
12

如果您查看 C 语法,则有许多上下文需要statement,该术语由语法本身定义。

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

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

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

但是由于大多数函数定义都包含多个声明和/或语句,因此允许这样做并没有太大的优势。

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

if (condition)
     statement;

是完全合法的,但是:

if (condition) {
    statement;
}

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

唯一一次我会省略大括号是当整个 if 语句或类似的东西适合单行时,这样做会使代码更易于阅读,并且我不太可能希望向每个语句添加更多语句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"); }
/* ... */
于 2013-02-15T19:59:31.680 回答
3

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

具体来说?当需要单个语句时,它是完全有效的。循环、if语句等都需要一个语句,它要么是一个块,要么是一个没有包含在块中的单个语句。

于 2013-02-15T19:29:51.240 回答
3

一个例子:

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

您可以使用有效的等效形式:

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

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

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

if (expression) statement

如果你想要一个多语句而不是单个语句,你可以使用一个被包围的复合语句{}

于 2013-02-15T19:30:52.773 回答
3

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

{
  x = 1;
  y = 2;
}

因此,如果您将上述内容放在ifelse大括号中的整个内容将作为一个整体执行,而如果您省略大括号,则只有第一个(x = 1;在这种情况下)将用作ifor的一部分else

您通常还可以将它们用于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";
于 2013-02-15T19:40:18.087 回答
2

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

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它预期的声明之后看到,因此您可以跳过大括号。

于 2013-02-15T19:33:28.283 回答
2

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

例子:

for (i = 0; i < j; i++ ) 
   foo(i);

while (1) 
   foo();

if( bool )
   foo();

void cheese()
   printf("CHEESE");

; 之后的所有内容 在上面的几行中,就像有 {} 一样,不算在块的“内部”。

于 2013-02-15T19:34:16.593 回答
1

如果有疑问,请使用大括号。它们不会“花费”任何额外费用[除非您绝对错误地使用它们]。

一个相当基本的规则是“如果你在同一个缩进中有多个分号,你应该有大括号”。这并不完全那么简单,但作为“一个没有如果、但是或其他并发症的句子”,它必须这样做。

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

于 2013-02-15T20:00:40.010 回答
0

从我刚刚回答的另一篇帖子中复制我自己的答案;显然可以使用没有花括号的 for 循环,并且实际上不离开括号!

#include <stdio.h>
int
 main(){
    for(int i=0; i<10;i++,printf("%d ",i),printf("%d\n",i));
 return 0;
}
1 ... 10

1 ... 10

希望任何人都觉得这很有用!

于 2021-04-18T21:04:31.487 回答
0

以下似乎有点棘手:

if (...)

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

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

于 2017-11-28T12:41:43.903 回答