/ / Під час розширення C макросу, чи існує спеціальний випадок для макросів, які розширюються до "/ *"? - c, макроси, c-препроцесор, c99

Під час розширення C макросу, чи є спеціальний випадок для макросів, які розширюються до "/ *"? - c, макроси, c-препроцесор, c99

Ось відповідний приклад. Це, очевидно, недійсне С, але я просто маю справу з препроцесором тут, тому код не треба скомпілювати.

#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: Розширення макросів та поводження з директивами".