Почему пустые выражения легальны в C/С++?

int main()
{
  int var = 0;; // Typo which compiles just fine
}

Ответы

Ответ 1

Это способ выражения C и С++ NOP.

Ответ 2

Как еще assert(foo == bar); скомпилировать без ничего, когда NDEBUG определено?

Ответ 3

Очевидно, что мы можем сказать такие вещи, как

for(;;) {
  // stuff
}

Кто мог бы жить без этого?

Ответ 4

Я не дизайнер языка, но ответ, который я бы дал, "почему бы и нет?" С точки зрения дизайна языка, вы хотите, чтобы правила (т.е. Грамматика) были как можно более простыми.

Не говоря уже о том, что используются "пустые выражения", т.е.

для (i = 0; я < INSANE_NUMBER; я ++);

Будет мертвый-ждать (не очень полезно, но использовать, тем не менее).

EDIT: Как указано в комментарии к этому ответу, любой компилятор, заслуживающий своей соли, вероятно, не будет ждать в этом цикле и оптимизирует его. Однако, если бы что-то более полезное в самой голове (отличной от я ++), которую я видел (как ни странно) с обходом структуры данных, то я предполагаю, что вы все равно можете построить цикл с пустым телом (используя/злоупотребляя конструкцией "для" ).

Ответ 5

Честно говоря, я не знаю, является ли это реальной причиной, но я думаю, что что-то более разумное - подумать об этом с точки зрения разработчика компилятора.

Большие части компиляторов создаются автоматическими инструментами, которые анализируют специальные классы грамматик. Кажется очень естественным, что полезные грамматики допускают пустые утверждения. Кажется, что ненужная работа обнаруживает такую ​​ "ошибку", когда она не изменяет семантику вашего кода. Пустой оператор ничего не сделает, поскольку компилятор не будет генерировать код для этих операторов.

Мне кажется, что это результат "Не исправить что-то, что не сломано"...

Ответ 6

Вы хотите иметь возможность делать такие вещи, как

while ( fnorble(the_smurf) == FAILED )
    ;

а не

while ( fnorble(the_smurf) == FAILED )
    do_nothing_just_because_you_have_to_write_something_here();

Но! Пожалуйста, не пишите пустой оператор в той же строке, как это:

while ( fnorble(the_smurf) == FAILED );

Это очень хороший способ запутать читателя, так как легко пропустить точку с запятой и поэтому думать, что следующая строка является телом цикла. Помните: программирование действительно связано с коммуникацией - не с компилятором, а с другими людьми, которые прочтут ваш код. (Или с собой, через три года!)

Ответ 7

ОК, я добавлю это в наихудший сценарий, который вы можете использовать:

for (int yy = 0; yy < nHeight; ++yy)
{
    for (int xx = 0; xx < nWidth; ++xx)
    {
        for (int vv = yy - 3; vv <= yy + 3; ++vv)
        {
            for (int uu = xx - 3; uu <= xx + 3; ++uu)
            {
                if (test(uu, vv))
                {
                    goto Next;
                }
            }
        }

    Next:;
    }
}   

Ответ 8

Наиболее распространенным случаем является, вероятно,

int i = 0;
for (/* empty*/; i != 10; ++i) {
    if (x[i].bad) break;
}
if (i != 10) {
    /* panic */
}

Ответ 9

При использовании ';' пожалуйста, имейте в виду одно. Это нормально:

a ? b() : c();

Однако это не скомпилируется:

a ? b() : ; ;

Ответ 10

while(1){
    ; /* do nothing */
}

Есть моменты, когда вы хотите сидеть и ничего не делать. Встроенное приложение, зависящее от события/прерывания, или когда вы не хотите, чтобы функция выходила, например, при настройке потоков и ожидании первого переключателя контекста.

Пример: http://lxr.linux.no/linux+v2.6.29/arch/m68k/mac/misc.c#L523