Использование препроцессора C для создания строкового литерала для scanf? - PullRequest
1 голос
/ 29 апреля 2010

Я пытаюсь создать строковый литерал sscanf, чтобы помочь в предотвращении переполнения буфера в C99. Цель примерно такая:

#define MAX_ARG_LEN   16

char arg[MAX_ARG_LEN] = "";

if (sscanf(arg, "%"(MAX_ARG_LEN-1)"X", &input) > 0)

Очевидное «ручное» решение выглядит примерно так:

#define MAX_ARG_LEN   16
#define MAX_ARG_CHARS "15"

char arg[MAX_ARG_LEN] = "";

if (sscanf(arg, "%"MAX_ARG_CHARS"X", &input) > 0)

Однако я бы предпочел, чтобы что-то автоматически генерировало «% 15X» при размере буфера 16. Эта ссылка почти работает для моего приложения: Преобразование токена препроцессора в строку но он не обрабатывает -1.

Предложения?

1 Ответ

7 голосов
/ 29 апреля 2010

Керниган и Пайк обсуждают эту проблему в своей (превосходной) книге ' Практика программирования ' и пришли к выводу, что наиболее надежный и портативный способ сделать это - использовать sprintf() для генерации строки формата .

Что вы можете сделать, это определить макрос как длину, исключая нулевой терминал, а затем использовать его следующим образом:

#define STR_EVALUATE(x)   #x
#define STRINGIFY(x)      STR_EVALUATE(x)
#define MAX_ARG_LEN 15
char arg[MAX_ARG_LEN+1] = "";

if (sscanf(arg, "%" STRINGIFY(MAX_ARG_LEN) "X", &input) > 0)
    ...

Или вы можете определить MAX_ARG_STRLEN как 15 и MAX_ARG_LEN как MAX_ARG_STRLEN + 1 и работать соответственно.

...