Почему пустые выражения допустимы в C / C ++? - PullRequest
16 голосов
/ 05 мая 2009
int main()
{
  int var = 0;; // Typo which compiles just fine
}

Ответы [ 11 ]

32 голосов
/ 05 мая 2009

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

13 голосов
/ 05 мая 2009

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

10 голосов
/ 05 мая 2009

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

for(;;) {
  // stuff
}

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

8 голосов
/ 05 мая 2009

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

Не говоря уже о том, что «пустые выражения» имеют применение, т.е.

для (i = 0; i

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

РЕДАКТИРОВАТЬ: Как указано в комментарии к этому ответу, любой компилятор, достойный его соли, вероятно, не будет занят в этом цикле и оптимизирует его. Однако, если бы в самом заголовке (кроме i ++) было что-то более полезное, что, как я видел, было сделано (странным образом) с обходом структуры данных, то я думаю, что вы все равно могли бы создать цикл с пустым телом (используя / злоупотребление конструкцией "for").

6 голосов
/ 05 мая 2009

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

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

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

5 голосов
/ 11 декабря 2011

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

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:;
    }
}   
5 голосов
/ 05 мая 2009

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

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 );

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

3 голосов
/ 05 мая 2009

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

int i = 0;
for (/* empty*/; i != 10; ++i) {
    if (x[i].bad) break;
}
if (i != 10) {
    /* panic */
}
2 голосов
/ 04 марта 2015

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

a ? b() : c();

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

a ? b() : ; ;
0 голосов
/ 10 июня 2018

Уже есть много хороших ответов, но мы еще не видели образец продуктивной среды.

Здесь - реализация FreeBSD strlen:

size_t
strlen(const char *str)
{
    const char *s;

    for (s = str; *s; ++s)
        ;
    return (s - str);
}
...