Об’єднайте int у рядок за допомогою C-попередника


90

Я намагаюся зрозуміти, як я можу об'єднати #define'd int у #define' d рядок, використовуючи C- препроцесор. Мій компілятор - GCC 4.1 на CentOS 5. Рішення також має працювати для MinGW.

Я хотів би додати номер версії до рядка, але єдиний спосіб, яким я можу змусити його працювати, - зробити копію номера версії, визначеного як рядки.

Найближчим, що я міг знайти, був метод цитування аргументів макросів, але він не працює для #defines

Це не працює.

#define MAJOR_VER 2
#define MINOR_VER 6
#define MY_FILE "/home/user/.myapp" #MAJOR_VER #MINOR_VER

Вона не працює без #з яких тому , що значення числа і буде розширюватися "/home/user/.myapp" 2 6, що не є дійсним C .

Це справді працює, але мені не подобається наявність копій визначень версії, оскільки вони мені також потрібні як цифри.

#define MAJOR_VER 2
#define MINOR_VER 6
#define MAJOR_VER_STR "2"
#define MINOR_VER_STR "6"
#define MY_FILE "/home/user/.myapp" MAJOR_VER_STRING MINOR_VER_STRING

Відповіді:


171

Класичне запитання препроцесора С ....

#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)

#define MAJOR_VER 2
#define MINOR_VER 6
#define MY_FILE "/home/user/.myapp" STR(MAJOR_VER) STR(MINOR_VER)

Додатковий рівень опосередкованості дозволить препроцесору розширити макроси, перш ніж вони будуть перетворені в рядки.


3
STR () у цьому випадку видасть вузький рядок. Чи існує варіант, щоб перетворити це на широкий рядок?
gkns

5
Я не міг сказати, скільки разів я погуглив і скопіював з цієї точної відповіді, але це буде двозначними цифрами
MightyPork

1
Перший "STR_HELPER" необхідний, оскільки '#' працює лише з аргументом макросу. Мені знадобилось колись це зрозуміти ..
clarkttfu

1
@clarkttfu, свого роду - так, #працює лише з аргументами макросів. Однак STR_HELPERмакрос необхідний, щоб уникнути перетворення макроса MAJOR_VERв рядок "MAJOR_VAR", де ми хочемо отримати результат "2".
Lindydancer

13

Робочим способом є запис MY_FILE як параметричного макросу:

#define MY_FILE(x,y) "/home..." #x #y

EDIT: Як зазначає "Lindydancer", це рішення не розширює макроси в аргументах. Більш загальне рішення:

#define MY_FILE_(x,y) "/home..." #x #y
#define MY_FILE(x,y) MY_FILE_(x,y)

1
На мою чесну думку, це найкраща відповідь і набагато простіша за інші пропозиції. Я здивований, що кращого рейтингу не отримали!
osirisgothra

5
Це чисте рішення, яке, на жаль, не працює. Якщо аргумент, який передано MY_FILEмакросу, скажіть Aі B, цей макрос розшириться до "/home..." "A" "B".
Lindydancer

2

Це можна зробити за допомогою BOOST_PP_STRINGIZE :

#define MAJOR_VER 2
#define MINOR_VER 6
#define MY_FILE "/home/user/.myapp" BOOST_PP_STRINGIZE(MAJOR_VER) BOOST_PP_STRINGIZE(MINOR_VER)

28
Змушує мене посміхатися, як люди кидають Boost на все.
Frerich Raabe

4
@Frerich: Доводячи ваш аргумент до крайності, людям слід писати власні компілятори спочатку в необробленому машинному коді, а не кидати g ++ у все ... Немає сенсу заново винаходити колесо. Хороші програмісти пишуть код, великі використовують повторно.
Максим Єгорушкін

@jonescb: просто відкрийте заголовок підсилення і переконайтесь самі.
Максим Єгорушкін

10
Так, я спробував. Це справді спрацювало, але використання заголовка Boost у програмі на C мені здається дивним.
jonescb

1
Ой, погано, не помітив Cтега.
Максим Єгорушкін
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.