LINUX.ORG.RU

Зачем писать statement в последней пустой секции switch?

 , ,


1

5

Итак, есть какой-то такой говнокод:

enum Whatever { ONE = 1, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT };

void foo(Whatever v) {
    switch (v) {
    case ONE:
    case TWO:
    case SIX:
        std::cout << v << std::endl;
    case THREE: // fallthrough
    default:
       break; // без хотябы ";" не компилируется: 
              // error: expected primary-expression before '}' token
    }
}

Вопрос: как ничего не делать и жить счастливо зачем в конце обязателен какой-нибудь statement? Почему что мешает сделать как в случае fallthrough?

Ответ на: комментарий от Deleted

А это вообще переносимо?

Если речь о компиляции — то да, скомпилируется любым (поддерживающим стандарт) компилятором C/C++.

Или это undefined behavior?

Ессесно. Прыжок в цикл без инициализации счётчика/условия.

KennyMinigun ★★★★★
() автор топика
Ответ на: комментарий от Pavval

Например, если нужно пройтись for() по всем элементам.

Но только когда элементы последовательные :)

KennyMinigun ★★★★★
() автор топика
Ответ на: комментарий от reprimand

Всё логично, нет?

Нет. Непонятно зачем после метки писать пустой стейтмент. Т.е. с точнки зрения стандарта уже растолковали мне выше, а вот с точки зрения логики — нет.

Вот насколько сложно понять куда пойдёт ход программы после прыжка на метку? Да элементарно: вниз по коду. Конечно, если изменят стандарт и позволят писать метки без стейтмента, то можно будет сделать что-то такое:

int function() {
    int result = 0;
   
    // bla-bla-bla
    if (isProgrammerStupid)
        goto ASS;
    // bla-bla-bla

    return result;
ASS:
}

Но как это сродни прыжкам внутрь цикла без инициализации условия выхода.

KennyMinigun ★★★★★
() автор топика
Последнее исправление: KennyMinigun (всего исправлений: 2)
Ответ на: комментарий от KennyMinigun

Нет. Непонятно зачем после метки писать пустой стейтмент.

После метки ОЖИДАЕТСЯ стейтмент. И если тебе ничего не нужно после метки - ты пишешь пустой стейтмент. Логика, как по мне, вполне себе нормальная.

reprimand ★★★★★
()
Ответ на: комментарий от reprimand

Да, такие правила синтаксиса. Но если отойти от такого понимания метки как в в бейсике «метка -> инструкция» в сторону «метка -> продолжение выполнения», то стейтмент после метки уже не кажется таким необходимым.

Вообще, приходится в некоторой мере согласиться с псто former_anonymous с начала топика. Даже в современном С++ со всеми его изощрениями довольно много легаси ограничений. Например те же инклюды и единицы компиляции: особенно весело, когда твой код компилируется, но не линкуется с ошибкой «undefined reference» на константу (или даже лучше: constexpr), которую объявил (declare), но забыл определить (define). Причём в случае constexpr не всегда нужно определять. И много-много других приколов.

KennyMinigun ★★★★★
() автор топика
Последнее исправление: KennyMinigun (всего исправлений: 1)
Ответ на: комментарий от KennyMinigun

Согласен что тупо. Кстати, подглядел у себя как я разруливал такие же енумы у себя — да, «иф, элзиф, элзиф, элз» потому и не натыкался на такое.

А вот насчет пустого стейтмента после метки — вполне жидаемо, вот тебе аналогия:

for (;;) break;

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple
for (;;) break;

Ага, прикольно, что условние по умолчанию true (хоть там ничего нет). По моему это хорошая фича (хотя while (true) как-то гуманней выглядит).

Ну тут уже со стороны логики врядли можно недвояко растолковать конструкцю for (;;) (без стейтмента). Ибо тогда бы пришлось как в JavaScript делать: конец строки = конец стейтмента (ито там с for не работает): http://ideone.com/8VQBwW

for (i = 0; i < 3; i++)

print("check")

print("once")

Кстати, подумал проверить такое (ниже) — не работает (ни одна метка):

for (INIT: int i = 0; TEST: i < 10; ACT: i++) {}

KennyMinigun ★★★★★
() автор топика
Последнее исправление: KennyMinigun (всего исправлений: 1)
Ответ на: комментарий от KennyMinigun

Вайлтру как-то не сивосемдесятдевятно )) Не суть.

По синтаксису — ";" это пустой оператор. Давай рассмотрим в свитче дефолт метку и завершающий её бряк как «begin...end» или «{...}». Как компилятор должен определить окончание этого блока? Всмысле, понятно, что может запомнить невнятное место тут, а пройдя дальше разгрести.

Но мое мнение таково, что это уже синтаксический сахар, а все эти сахарА только усложняют парсер и, возможно, расслабляют писателей кода. Скорее всего, примерно так думали и те, кто писал спеки и парсер для компиля.

deep-purple ★★★★★
()
Ответ на: комментарий от Deleted

Но при этом duff's device вроде как вполне допустим.

void Send(int * to, const int* from, const int count)
{
    int n = (count+7) / 8;
    switch(count%8)
    {
       case 0: do { *to++ = *from++;
       case 7:      *to++ = *from++;
       case 6:      *to++ = *from++;
       case 5:      *to++ = *from++;
       case 4:      *to++ = *from++;
       case 3:      *to++ = *from++;
       case 2:      *to++ = *from++;
       case 1:      *to++ = *from++;
        } while (--n>0);
    }
}

deadskif
()
Ответ на: комментарий от KennyMinigun

Даже в современном С++ со всеми его изощрениями довольно много легаси ограничений. Например те же инклюды и единицы компиляции: особенно весело, когда твой код компилируется, но не линкуется с ошибкой «undefined reference» на константу (или даже лучше: constexpr), которую объявил (declare), но забыл определить (define). Причём в случае constexpr не всегда нужно определять. И много-много других приколов.

Это не легаси ограничения, просто ты не догоняешь как работает язык.

mashina ★★★★★
()
Ответ на: комментарий от KennyMinigun

то стейтмент после метки уже не кажется таким необходимым.

Наверно, что бы не было такого.

int lol(int a, int b) {
l: 
    int i = 0;
    i = a + b;
    if (i > 10)
        goto l;
    return i;
}

deadskif
()
Ответ на: комментарий от deadskif

А что в том куске кода не так? Он уже сейчас компилируется и работает: http://ideone.com/YcLXgw

P.S. Ну ок, там вечный цикл без условия выхода. Я его немного поменял.

KennyMinigun ★★★★★
() автор топика
Последнее исправление: KennyMinigun (всего исправлений: 1)
Ответ на: комментарий от mashina

Мне кажеться, ты ошибаешся: я вполне себе понимаю когда надо определять constexpr (хранилище нужно), а когда нет (хранилище не нужно). Тут вообще идётся не про мое «догоняние языка», а про то, что некоторый аспект (или даже аспекты) был поставлен под сомнение и может быть усовершенствован.

KennyMinigun ★★★★★
() автор топика
Последнее исправление: KennyMinigun (всего исправлений: 1)
Ответ на: комментарий от KennyMinigun

g++ компилирует, если поменять std::out на printf() и компилять gcc — то нет.

Но вообще, наверно ничего такого действительно нету.

deadskif
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.