C: Лучший способ скрыть оператор if в макросе

#c #macros #c-preprocessor

#c #макросы #c-препроцессор

Вопрос:

В чем лучше всего скрывать оператор if #define ?

  1. Вы можете использовать if в define:
 #define MY_MACRO(isTrue) if(isTrue) do()
  

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

  1. Вы можете использовать тернарный оператор:
 #define MY_MACRO(isTrue) (isTrue) ? do() : do_not()
//OR
#define MY_MACRO(isTrue) (isTrue) ? do() : (void)0
  

Здесь я понимаю, почему это нехорошо. Например, любой может вызвать вашу функцию do() с помощью простого true || MY_MACRO(?)

  1. Мое текущее решение этой проблемы — do-while-false
 #define MY_MACRO(isTrue) do { if(isTrue) do(); } while (false)
  

Действительно ли это лучший подход? Что плохого может случиться с этим макрокомандой?

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

1. Зачем вам нужно его усложнять?

2. Я предполагаю, что do() предполагается, что это функция, а не использование do ключевого слова, верно?

3. Какова наилучшая практика скрытия оператора if в #define — лучшая практика — не делать этого.

4. «любой может вызвать вашу функцию do() с помощью » -> Ничто из этого не помешает кому-либо вызвать do() функцию.

Ответ №1:

Для 1 его нельзя использовать таким образом:

 if (foo) MY_MACRO(bar);
else something_else();
  

Потому что это было бы расширено следующим образом:

 if (foo) {
    if (isTrue) {
        do();
    } else {
        something_else();
    }
}
  

else Будет (неожиданно) else для if внутри макроса.

Плохая особенность вашего текущего подхода заключается в том, что его нельзя использовать там, где требуется оператор (например, f((MY_MACRO(a), b), c) в выражении через запятую не будет работать), но поскольку вы используете его для побочных эффектов do() , он не будет использоваться там, где требуется оператор.

Поскольку он кажется довольно коротким, вы можете заставить его действовать как оператор, просто добавьте еще одну пару скобок, чтобы решить вашу проблему с помощью 2:

 #define MY_MACRO(isTrue) ((isTrue) ? do() : (void)0)
  

Вы также должны захотеть рассмотреть static conditional_do(bool isTrue) { if (isTrue) { do(); } } вместо макроса.