2008-10-27 3 views
40

Я ищу способ преобразования токена препроцессора в строку.Преобразование токена препроцессора в строку

В частности, я где-то есть:

#define MAX_LEN 16 

, и я хочу использовать его, чтобы предотвратить переполнение буфера:

char val[MAX_LEN+1]; // room for \0 
sscanf(buf, "%"MAX_LEN"s", val); 

Я открыт для других способов сделать то же самое, но только стандартная библиотека.

+0

http://stackoverflow.com/questions/195975/how-to-make-a-char-string-from-ac-macros-value – 2015-10-05 13:43:46

+0

Возможный дубликат [C Макросов для создания строк] (http: // переполнение стека.com/questions/798221/c-macros-to-create-strings) – rjstelling 2015-10-06 10:33:35

ответ

78

см http://www.decompile.com/cpp/faq/file_and_line_error_string.htm а именно:

#define STRINGIFY(x) #x 
#define TOSTRING(x) STRINGIFY(x) 
#define AT __FILE__ ":" TOSTRING(__LINE__) 

так что ваша проблема может быть решена путем делать sscanf(buf, "%" TOSTRING(MAX_LEN) "s", val);

+0

почему каскадирование 2 макросов? Не было бы ТОТРИРОВАТЬ достаточно? – 2017-10-05 12:52:11

19

Я нашел ответ онлайн.

#define VERSION_MAJOR 4 
#define VERSION_MINOR 47 

#define VERSION_STRING "v" #VERSION_MAJOR "." #VERSION_MINOR 

выше не работает, но мы надеемся, иллюстрирует то, что я хотел бы сделать, т.е. сделать VERSION_STRING в конечном итоге, как «v4.47».

Для создания правильной цифровой форме использовать что-то вроде

#define VERSION_MAJOR 4 
#define VERSION_MINOR 47 

#define STRINGIZE2(s) #s 
#define STRINGIZE(s) STRINGIZE2(s) 
#define VERSION_STRING "v" STRINGIZE(VERSION_MAJOR) \ 
"." STRINGIZE(VERSION_MINOR) 

#include <stdio.h> 
int main() { 
    printf ("%s\n", VERSION_STRING); 
    return 0; 
} 
+5

«STRINGIZE» звучит ужасно .. – Blindy 2010-04-25 20:06:02

4

Это было некоторое время, но это должно работать:

sscanf(buf, "%" #MAX_LEN "s", val); 

Если нет, то нужно «двойное расширение»:

#define STR1(x) #x 
#define STR(x) STR1(x) 
sscanf(buf, "%" STR(MAX_LEN) "s", val); 
+1

Первый не работает; # строит макро аргументы в расширениях макросов. Второй будет работать. – 2008-10-27 15:55:14

2

Вы должны использовать трюк stringification макро двойного расширения. Или просто введите

#define MAX_LEN 16 
#define MAX_LEN_S "16" 

char val[MAX_LEN+1]; 
sscanf(buf, "%"MAX_LEN_S"s", val); 

и держать его в синхронизации. (Это немного беспокоит, но пока определения находятся рядом друг с другом, вы, вероятно, помните.)

На самом деле, в данном конкретном случае не хватит strncpy?

strncpy(val, buf, MAX_LEN); 
val[MAX_LEN] = '\0'; 

Если бы это было printf, хотя это было бы проще:

sprintf(buf, "%.*s", MAX_LEN, val); 
1

В то время как некоторые из указанных выше «работы», лично я бы рекомендовал только с помощью простой строки API вместо dreck это происходит в libc. Существует несколько портативных API-интерфейсов, некоторые из которых также оптимизированы для простоты включения в ваш проект ... и некоторые из них, например, ustr, имеют небольшие накладные расходы и поддерживают переменные стека.