#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/v3Kroo2. Завершение макроса с
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? Лучший вопрос: не могли бы вы сделать это лучше / чище? Если да: сделайте это, а не только критикуйте его.