в C возможно ли иметь макрос с условным оператором break

#c #macros #switch-statement #break

#c #макросы #switch-statement #break

Вопрос:

Возможна ли следующая идея в C?

Мне не удалось достичь. (используя онлайн-компилятор c для проверки этого)

Возможно, это решаемо с помощью GOTO, но это нежелательно.

Просто теоретически, если есть какое-либо другое решение, которого мне не хватает, но идея состоит в том, чтобы statemachine был немного более эффективным.

 #include <stdio.h>
#include <stdint.h>

uint8_t shouldhavebreaked = 0;
#define BREAK_CONDITIONAL(x,y) do { if(x == y) { shouldhavebreaked = 1; break ;}  } while(0)

int main()
{
    uint8_t swh = 0;

    switch (swh)
    {

    case 0:
 
    /*if state is same, break, otherwise fall-through*/
    BREAK_CONDITIONAL(swh, 0);

    case 1:
        printf("failed n");
        break;

    }
    printf("changed? %d n",shouldhavebreaked);
    return 0;
}
 

Комментарии:

1. break Завершает do цикл внутри макроса, а не switch . Удалите цикл в макросе.

2. Я бы предложил писать if ( swh == 0 ) break; , а не запутывать поток управления с помощью макроса

3. @M.M В общем, я согласен, но есть случаи (например, конечные автоматы), когда вы можете создавать крошечные языки , используя набор символьных макросов.

Ответ №1:

Вместо funky do{}while() вы могли бы использовать менее напуганный if(){} else :


 #define BREAK_CONDITIONAL(x,y) if(x == y) { shouldhavebreaked = 1; break; } else
 

И хорошей привычкой является заключать аргументы в скобки в макросах:


 #define BREAK_CONDITIONAL(x,y) if((x)==(y)) { shouldhavebreaked=1;break;} else
 

Комментарии:

1. Использование этого монстра приводит к BREAK_CONDITIONAL(a,b) c = a b; тому, что это за язык? Никогда не советуйте эту ерунду. Одно из худших злоупотреблений макросами, которые когда-либо видели. godbolt.org/z/v3Kroo

2. Завершение макроса с else помощью хуже, чем без запроса ;

3. я принимаю этот ответ, я не использую else, и программа строится без else, поэтому я счастлив на данный момент, я пока не понимаю побочных эффектов. Бонусом было бы, если бы каким-то образом имя выделялось как ключевое слово, например, какой-нибудь typedef.. чтобы люди увидели, что это функция, подобная break

4. Если вы можете избежать dangling else , все в порядке. ( goto вариант может быть более надежным, но я не хочу вызывать здесь еще одну религиозную войну …)

Ответ №2:

Такие макросы не имеют никакого смысла (если только вы не хотите сделать код более сложным для чтения, понимания и поддержки. Это также будет более подвержено ошибкам). Избегайте как чумы. Они выглядят как функции, и это не так.

Если я скрою макрос из ответа @wildplasser, можете ли вы догадаться, что делает эта ерунда?

     if(c)
    {
        BREAK_CONDITIONAL(a,b) c = a b;
    }
 

Комментарии:

1. В этом случае (поскольку внутри if() детали есть разрыв) он будет делать то же самое. Он dangling else будет связан с самым внутренним if , как и предполагалось.

2. @wildplasser Я думаю, вы не понимаете.

3. Но почему вы ожидаете, что пропуск a ; приведет к желаемому поведению? В вашем случае это не приведет к синтаксической ошибке (как в do{}while() случае с funky).

4. @wildplasser Наверняка вы не понимаете. Оба не имеют никакого смысла

5. @P__JsupportswomeninPoland вы когда-нибудь читали вывод yacc / bison? Лучший вопрос: не могли бы вы сделать это лучше / чище? Если да: сделайте это, а не только критикуйте его.