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