Преобразование токена препроцессора в строку
Я ищу способ преобразовать токен препроцессора в строку.
в частности, у меня где-то есть:
#define MAX_LEN 16
и я хочу использовать его для предотвращения переполнения буфера:
char val[MAX_LEN+1]; // room for
sscanf(buf, "%"MAX_LEN"s", val);
Я открыт для других способов сделать то же самое, но только стандартной библиотеки.
5 ответов
см.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);
Я нашел ответ в интернете.
#define VERSION_MAJOR 4 #define VERSION_MINOR 47 #define VERSION_STRING "v" #VERSION_MAJOR "." #VERSION_MINOR
выше не работает, но надеюсь иллюстрирует, что я хотел бы сделать, т. е. сделать VERSION_STRING в конечном итоге как "В4.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; }
прошло некоторое время, но это должно работать:
sscanf(buf, "%" #MAX_LEN "s", val);
Если нет, ему нужно будет "двойное расширение" трюк:
#define STR1(x) #x
#define STR(x) STR1(x)
sscanf(buf, "%" STR(MAX_LEN) "s", val);
вы должны использовать трюк макроса 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] = '';
если бы это было printf
, хотя, это было бы проще:
sprintf(buf, "%.*s", MAX_LEN, val);
хотя некоторые из вышеперечисленных "работают", лично я бы рекомендовал просто использовать простой строковый API вместо dreck, который поставляется в libc. Существует ряд портативных API, некоторые из которых также оптимизированы для удобства включения в проект ... а некоторые любят устр имейте крошечные накладные расходы космоса и поддержку для переменных стога.