Страницы

Поиск по вопросам

пятница, 20 декабря 2019 г.

Вопрос по подстановкам #define языка СИ

#c


Есть такой рабочий код:

#include 

#define T 50
#define str(s) strk(s)
#define strk(s) #s

int main ()
{
 puts(str(T));
}


Мы знаем что puts по прототипу не сможет вывести число, только строки.
Я не понял, какую роль играют вот эти две строчки для вывода числа через подстановку
(в нашем случае для T, вместо которого будет подставляться целое число) из puts:

#define str(s) strk(s)
#define strk(s) #s


И зачем мы делаем подстановку к функции str(s) эту функцию strk(s) с произвольным
именем (вместо str(s) и strk(s) можно писать что угодно и программа все равно заработает
без ошибок)? Напоследок, что означает #s в данном примере?
    


Ответы

Ответ 1



Это такой хитрый способ заставить С рассматривать 50 не как число (и приводить к типу int), а как строку «50» (и превращать в последовательность байтов 0x30 0x35 0x00). Это делается как раз макросом с решеткой: #define strk(s) #s Решетка служит указанием — «рассматривай всю бурду, что попала в s, как строку». Убедитесь с помощью ideone. А этот макрос: #define str(s) strk(s) нужен для того, чтобы первая подстановка #define T 50 раскрылась и заменилась на 50. Если сразу сделать strk(T), программа превратит T в строку и напечатает «T». Это свойство можно использовать для формирования отладочного вывода: #define PRINT(A) printf(#A " = %d\n", A);

Ответ 2



В дополнение. Посмотрим на это: #define T 50 #define str(s) #s int main() { puts( str(T) ); return 0; } Прогоним через препроцессор и получим: int main() { puts( "T" ); return 0; } То есть в таком варианте макрос str() будет превращать в строку не значение аргумента, а его имя :) Дополнтельный прогон через ещё один макрос и нужен потому, что в него попадёт уже именно значение (в нашем случае - 50).

Комментариев нет:

Отправить комментарий