int main()
{
int var = 0;; // Typo which compiles just fine
}
Почему пустые выражения легальны в C/С++?
Ответ 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