C: Лучший способ скрыть оператор if в макросе - PullRequest
0 голосов
/ 04 апреля 2019

Какова лучшая практика сокрытия оператора if в #define?

  1. Вы можете использовать if в определении:
#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 Ответ

1 голос
/ 04 апреля 2019

Для 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(); } } вместо макроса.

...