Преобразовать токен препроцессора в строку
-
04-07-2019 - |
Вопрос
Я ищу способ преобразования токена препроцессора в строку.
В частности, я где-то получил:
#define MAX_LEN 16
и я хочу использовать его для предотвращения переполнения буфера:
char val[MAX_LEN+1]; // room for \0
sscanf(buf, "%"MAX_LEN"s", val);
Я открыт для других способов достижения того же, но только для стандартной библиотеки.
Решение
см. 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 в итоге & Quot; v4.47 & Quot;. Р>
Для генерации правильной числовой формы использовать что-то вроде
#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);
Вы должны использовать трюк макросов с двойным расширением. Или просто есть
#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);
Хотя некоторые из вышеперечисленных «работают», лично я бы порекомендовал просто использовать простой строковый API вместо dreck, который есть в libc. Существует ряд переносимых API, некоторые из которых также оптимизированы для простоты включения в ваш проект ... а некоторые, например, У ustr небольшие накладные расходы и поддержка переменных стека.