Когда я могу опустить фигурные скобки в C?

Я почти уверен, что это было задано раньше, но я не могу найти ответа на него где-нибудь.

Когда я могу опустить фигурные скобки в C? Ранее я видел безрежимные выражения return, такие как

if (condition)
  return 5;

Но это не всегда работает для всех операторов, т.е. при объявлении метода.

изменить:

Являются ли правила для удержания без изменений такими же, как в Java?

Ответ 1

Если вы посмотрите на синтаксис C, существует ряд контекстов, для которых требуется оператор, термин, который определяется самой грамматикой.

В любом из этих контекстов одним из форм оператора, который вы можете использовать, является составной оператор, состоящий из открывающей скобки {, последовательности из нуля или более деклараций и/или операторов и закрывающей скобки }. (В C90 все объявления в составном заявлении должны предшествовать всем операторам, C99 удалил это ограничение.)

Для определения функции явно требуется составной оператор, а не только какой-либо оператор. (Я думаю, что единственный случай, когда составной оператор является единственным типом оператора, который вы можете использовать). Если не для этого ограничения, вы сможете написать:

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

Но так как большинство определений функций содержат множественные объявления и/или инструкции, не было бы большого преимущества в разрешении этого.

Есть отдельный вопрос: когда вы должны опустить фигурные скобки. По моему личному мнению, ответ "почти никогда". Это:

if (condition)
     statement;

является совершенно законным, но это:

if (condition) {
    statement;
}

IMHO читает лучше и легче поддерживать (если я хочу добавить второй оператор, фигурные скобки уже есть). Это привычка, которую я выбрал из 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"); }
/* ... */

Ответ 2

Единственными местами, где вы можете опустить скобки, являются тела операторов 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(); 

Не делай этого.

Ответ 3

Но это не всегда работает для всех операторов.

В частности? Когда ожидается одно утверждение, оно отлично действует. Циклы, оператор if и т.д. Все ожидают утверждения и что либо блок, либо, ну, один оператор, не будучи заключенным в блок.

Ответ 4

Пример:

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

вы можете использовать действительную эквивалентную форму:

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

Некоторые подробные компиляторы могут предупреждать, но это действительно.

Обратите внимание, что для оператора if (то же самое для while, оператора for,...) {} не пропущены. Их просто не запрашивают. Оператор if имеет этот синтаксис:

if (expression) statement

Если вам требуется несколько операторов вместо одного оператора, вы можете использовать составной оператор, который окружен {}.

Ответ 5

В основном вам нужны фигурные скобки, когда вы хотите объединить несколько операторов или выражений в один, например:

{
  x = 1;
  y = 2;
}

Итак, если вы поместите выше в if или else, все это в фигурных скобках будет выполнено в целом, тогда как если вы опустите фигурные скобки, то только первый (x = 1; в этом случае) будет использоваться как часть if или 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";

Ответ 6

В любое время есть блок с более чем одной строкой (подсчет строк как один оператор с;)

<сильные > Примеры:

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

while (1) 
   foo();

if( bool )
   foo();

void cheese()
   printf("CHEESE");

Все после; в приведенных выше строках не считается "внутри" блока, как если бы они были {}.

Ответ 7

Вы можете опустить их, когда есть один оператор, который вы выполняете:

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 specification, что правила одинаковы. Я специально привязался к разделу if, но после if он ожидал утверждения, поэтому вы можете пропустить фигурные скобки.

Ответ 8

Если есть сомнения, используйте фигурные скобки. Они не "стоят" лишних [если вы не используете их неправильно].

Довольно основное правило: "Если у вас более одной точки с запятой в том же отступе, у вас должны быть фигурные скобки". Это не совсем так просто, но, как "одно предложение без каких-либо проблем, новых или других осложнений", это нужно будет сделать.

И да, Java, основанный на C-синтаксисе, имеет одни и те же основные правила - возможно, какая-то странность, когда Java отличается от C или С++, но это необычные/странные вещи, а не то, что вы обычно нажимаете при написании типичных code [Я не сделал много java, поэтому не могу сказать, что я нашел их, но я уверен, что есть НЕКОТОРЫЕ отличия - в конце концов, это разные языки.

Ответ 9

Следующее выглядит немного сложным:

if (...)

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

Я предполагаю, что препроцессор C заботится о пустых строках, так что это утверждение отлично. Конечно, очень плохая практика.