Должен ли #define добавлять пробелы вокруг макросов? - PullRequest
3 голосов
/ 09 мая 2009

Я смотрел на программу на http://www0.us.ioccc.org/1988/westley.c,, упомянутом в еще один SO-ответ - предполагается, что значение pi должно быть около 3.142, но когда я его скомпилирую и запусту, получу 0.250. Похоже, когда препроцессор GCC (как проверенный 4.1.2, так и 3.4.6) работает в коде, он конвертирует

#define _ -F<00||--F-OO--;
_-_-_

до

-F<00||--F-OO--;- -F<00||--F-OO--;- -F<00||--F-OO--;

но я думаю, чтобы программа работала, она должна быть

-F<00||--F-OO--;--F<00||--F-OO--;--F<00||--F-OO--;

т.е. GCC вставляет дополнительный пробел перед расширением "macro". Это способ, которым #define должен работать? (Это изменилось с 1988 года?)

РЕДАКТИРОВАТЬ : Также будет полезна любая информация о том, как предотвратить появление этих пробелов.

Ответы [ 4 ]

11 голосов
/ 09 мая 2009

Только намного более старые препроцессоры не вставляли это дополнительное пространство - обратите внимание, что оригинальная запись была представлена ​​более 20 лет назад в 1988 году, до того, как версия стандарта С в 1989 году была стандартизирована. Вы можете передать флаг -traditional-cpp препроцессору GCC, что заставит его имитировать поведение старомодных препроцессоров C, в отличие от препроцессоров ISO C.

6 голосов
/ 09 мая 2009

Препроцессор работает с токенами, а не только с текстом. Так что технически он не «ставит пробел» между ними, но если вы явно не скажете ему вставить два токена вместе с оператором ##, он не сделает этого. В этом случае два - через строки макроса считаются двумя разными токенами - оба означают унарный минус, а не декремент.

см. Также: http://en.wikipedia.org/wiki/C_preprocessor#Token_concatenation

5 голосов
/ 09 мая 2009

Из стандарта C99:

Директива предварительной обработки вида

# определение идентификатора списка замен новой строки

определяет объектоподобный макрос, который вызывает замену каждого последующего экземпляра имени макроса списком замены токенов предварительной обработки, которые составляют остаток директивы.

Таким образом, макросы работают с токенами и ожидается пробел.

И вы можете получить желаемый результат, используя оператор вставки токена, ##, но для этого вам нужно использовать еще несколько макросов:

#define PASTE2( x, y) x##y
#define PASTE( x, y) PASTE2(x, y)

#define _ -F<00||--F-OO--;


PASTE(PASTE(PASTE(PASTE(_,-),_),-),_)

Так что я не уверен, что это реальный ответ для вас.

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

_ PASTE(-,_) PASTE(-,_)

Я все еще сомневаюсь, что ты этого хочешь.

0 голосов
/ 09 мая 2009

Да, gcc вставляет лишние пробелы (проверьте, проверив вывод stdout gcc -E westley.c (. Насколько я знаю, это поведение соответствует стандарту.

...