Подтвердить что ты не робот

Неправильно ли добавлять директивы препроцессора в функционально-подобный макрос?

Я знаю, что мой вопрос похож на этот или этот, но я считаю, что это на самом деле не то же самое, и, более того, у второго ответа нет ответа, я решил спросить, правильно ли добавлять директивы препроцессора при вызове функционально-подобного макроса?

В моем случае у меня есть макрос функции:

#define FUNC_MACRO(a, b)  // do something with the variables

и где-то в коде я вызываю его с определенной разницей, если определен какой-то другой макрос:

// ...
FUNC_MACRO(aVal
#ifdef ANOTHER_MACRO
                + offset
#endif // ANOTHER_MACRO
           , bVal);
// ...

Я тестировал на своей машине (linux, с gcc 4.8), и он работал нормально (с директивами препроцессора и без них и с и без ANOTHER_MACRO), но безопасно ли это сделать?

Я прочитал абзац 16.3/9 из ответа на первый подобный вопрос, но верно ли это и для моего случая?

4b9b3361

Ответ 1

Язык C оставляет это как поведение undefined в 6.10.3 Замена макроса, ¶11:

Если в списке аргументов есть последовательности токенов предварительной обработки, которые в противном случае действовали бы как директивы предварительной обработки, поведение undefined.

И действительно, неправильно это делать.

GCC и, возможно, другие популярные компиляторы не поймают его, поэтому, вероятно, многие пользователи этого языка не знают. Я столкнулся с этим, когда некоторые из моего кода не удалось скомпилировать на PCC (и быстро исправили ошибку в моем коде).

Обновление: PJTraill задал в комментариях случай, когда было бы "вводящим в заблуждение или бессмысленным" иметь директивы препроцессора внутри расширения макросов. Здесь очевидный:

    foo(a, b,
#ifdef BAR
        c);
#else
        d);
#endif

Я не уверен, было бы правдоподобным, если бы язык указывал, что сбалансированные условия препроцессора внутри расширения макросов в порядке, но я думаю, что у вас также возникнут проблемы с неопределенностями в том порядке, в котором они должны обрабатываться.

Ответ 2

Сделайте вместо этого следующее:

#ifdef ANOTHER_MACRO
FUNC_MACRO(aVal + offset, bVal);
#else
FUNC_MACRO(aVal, bVal);
#endif

РЕДАКТИРОВАТЬ: Решение проблемы, вызванной комментариями; Я не знаю, является ли метод OP специально неправильным (я думаю, что другие ответы охватывают это). Тем не менее, сжатость и ясность - это два аспекта, которые считаются очень важными при кодировании с C.

Как таковой, я бы предпочел найти лучшие способы достижения того, что, по-видимому, пытается попробовать ОП, слегка переосмыслив ситуацию, такую, какую я предложил выше. Я думаю, что OP, возможно, использовал тривиализованный пример, но обычно я нахожусь в большинстве ситуаций C, если что-то становится чрезмерно сложным или пытается что-то сделать, это не похоже на то, что язык должен позволять, тогда есть лучшие способы достичь того, что необходимо.