Ось відповідний приклад. Це, очевидно, недійсне С, але я просто маю справу з препроцесором тут, тому код не треба скомпілювати.
#define IDENTITY(x) x
#define PREPEND_ASTERISK(x) *x
#define PREPEND_SLASH(x) /x
IDENTITY(literal)
PREPEND_ASTERISK(literal)
PREPEND_SLASH(literal)
IDENTITY(*pointer)
PREPEND_ASTERISK(*pointer)
PREPEND_SLASH(*pointer)
Запуск попереднього процесора gcc на ньому:
gcc -std=c99 -E macrotest.c
Це дає:
(...)
literal
*literal
/literal
*pointer
**pointer
/ *pointer
Будь ласка, зверніть увагу на додатковий пробіл у останньому рядку.
Це виглядає як функція запобігання макросамрозширюючись до "/ *" для мене, що я добре впевнений, але з першого погляду я не міг знайти щось, що стосується цієї поведінки в стандарті C99. Тоді знову я недосвідчений у С. Чи може хтось пролити світло на це? Де це вказано? Я б припустив, що компілятор, що дотримується C99, не повинен просто вставляти додаткові пробіли під час розгортання макросів, тому що це, ймовірно, запобігає помилкам програмування.
Відповіді:
15 для відповіді № 1Вихідний код вже токенований, перш ніж він буде оброблений CPP.
Так що у вас є а /
і a *
токен, який не буде поєднано неявно з a /*
"token" (оскільки / * насправді не є токеном препроцесора, який я помістив у "").
Якщо ви використовуєте -E для випуску попередньо обробленого джерела, CPP потрібно вставити пробіл, щоб уникнути /*
будучи прочитаний наступним пакетом компілятора.
Ця ж функція запобігає двом, наприклад +
знаки з різних макросів об'єднуються в a ++
токен на виході.
Єдиний спосіб дійсно вставити два токенти препроцесора разом з ## оператором:
#define P(x,y) x##y
...
P(foo,bar)
призводить до токену foobar
P(+,+)
призводить до токену ++
, але
P(/,*)
недійсний з моменту /*
не є дійсним токеном препроцесора.
5 для відповіді № 2
Поведінка попереднього процесора стандартизована. У підсумку на http://en.wikipedia.org/wiki/C_preprocessor , результати, які ви спостерігаєте, є наслідком:
"3: Tokenization - препроцесор розбиває результат на попередньо оброблені токени та пробіли, він замінює коментарі з пробілами".
Це відбувається до:
"4: Розширення макросів та поводження з директивами".