Ответ 1
Это способ выражения C и С++ NOP.
int main()
{
int var = 0;; // Typo which compiles just fine
}
Это способ выражения C и С++ NOP.
Как еще assert(foo == bar);
скомпилировать без ничего, когда NDEBUG
определено?
Очевидно, что мы можем сказать такие вещи, как
for(;;) {
// stuff
}
Кто мог бы жить без этого?
Я не дизайнер языка, но ответ, который я бы дал, "почему бы и нет?" С точки зрения дизайна языка, вы хотите, чтобы правила (т.е. Грамматика) были как можно более простыми.
Не говоря уже о том, что используются "пустые выражения", т.е.
для (i = 0; я < INSANE_NUMBER; я ++);
Будет мертвый-ждать (не очень полезно, но использовать, тем не менее).
EDIT: Как указано в комментарии к этому ответу, любой компилятор, заслуживающий своей соли, вероятно, не будет ждать в этом цикле и оптимизирует его. Однако, если бы что-то более полезное в самой голове (отличной от я ++), которую я видел (как ни странно) с обходом структуры данных, то я предполагаю, что вы все равно можете построить цикл с пустым телом (используя/злоупотребляя конструкцией "для" ).
Честно говоря, я не знаю, является ли это реальной причиной, но я думаю, что что-то более разумное - подумать об этом с точки зрения разработчика компилятора.
Большие части компиляторов создаются автоматическими инструментами, которые анализируют специальные классы грамматик. Кажется очень естественным, что полезные грамматики допускают пустые утверждения. Кажется, что ненужная работа обнаруживает такую "ошибку", когда она не изменяет семантику вашего кода. Пустой оператор ничего не сделает, поскольку компилятор не будет генерировать код для этих операторов.
Мне кажется, что это результат "Не исправить что-то, что не сломано"...
Вы хотите иметь возможность делать такие вещи, как
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 );
Это очень хороший способ запутать читателя, так как легко пропустить точку с запятой и поэтому думать, что следующая строка является телом цикла. Помните: программирование действительно связано с коммуникацией - не с компилятором, а с другими людьми, которые прочтут ваш код. (Или с собой, через три года!)
ОК, я добавлю это в наихудший сценарий, который вы можете использовать:
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:;
}
}
Наиболее распространенным случаем является, вероятно,
int i = 0;
for (/* empty*/; i != 10; ++i) {
if (x[i].bad) break;
}
if (i != 10) {
/* panic */
}
При использовании ';' пожалуйста, имейте в виду одно. Это нормально:
a ? b() : c();
Однако это не скомпилируется:
a ? b() : ; ;
while(1){
; /* do nothing */
}
Есть моменты, когда вы хотите сидеть и ничего не делать. Встроенное приложение, зависящее от события/прерывания, или когда вы не хотите, чтобы функция выходила, например, при настройке потоков и ожидании первого переключателя контекста.
Пример: http://lxr.linux.no/linux+v2.6.29/arch/m68k/mac/misc.c#L523