Какая разница между макросами: #define STR (x) #x "и" #define STR (x) VAL (x) "с" #define VAL (x) #x "?

Когда я использую этот код:

#include <stdio.h>
#define STR(x) #x

int main(void)
{
    printf(__FILE__ STR(__LINE__) "hello!\n");
    return 0;
}

он печатает

hello.c__LINE__hello!

но когда я использую это:

#include <stdio.h>
#define STR(x) VAL(x)
#define VAL(x) #x

int main(void)
{
    printf(__FILE__ STR(__LINE__) "hello!\n");
    return 0;
}

он печатает

hello.c7hello!

какая разница между

#define STR(x) #x

и

#define STR(x) VAL(x)
#define VAL(x) #x

Ответы

Ответ 1

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

В первом случае аргумент STR не является макрорасширением, поэтому вы просто получаете имя макроса LINE.

Во втором случае аргумент STR макросвобождается, когда он подставляется в определение VAL, и поэтому он работает - вы получаете фактический номер строки, потому что макрос LINE расширяется.

Ответ 2

C99 N1256 стандартный проект 6.10.3.1/1 "Подстановка аргумента":

После того, как были определены аргументы для вызова функционально-подобного макроса, имеет место замена аргумента. Параметр в списке замещения, если не указано с помощью токена # или ## предварительной обработки или с помощью токена ## предварительной обработки (см. ниже), является заменяется соответствующим аргументом после того, как все макросы, содержащиеся в нем, были расширен. Перед заменой, каждый токен предварительной обработки аргументов полностью макрос заменили, как если бы они сформировали остальную часть файла предварительной обработки; нет другого доступны токеты предварительной обработки.

Итак, # и ## аргументы обрабатываются по-разному.