#define должно добавить пробелы вокруг макросов?

Я смотрел программу на 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 года?)

EDIT: Также будет оценена любая информация о том, как предотвратить появление этих пробелов.

Ответы

Ответ 1

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

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

Ответ 2

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

Ответ 3

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

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

# определить идентификатор замены-списка new-line

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

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

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

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

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


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

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

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

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

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

Ответ 4

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