Помогите gcc не предупреждать о том, что не используется строка формата строкового литерала

Я создаю функцию на C для преобразования значения индекса в строку, которая представляет собой подробное описание «поля», представленного индексом.

Итак, у меня есть хороший массив со всеми подробными описаниями, проиндексированными по индексу.

Чтобы сбросить его в буфер, я использую такой код

#define BUFFER_SIZE 40
void format_verbose(uint32_t my_index,
                    char     my_buffer[BUFFER_SIZE])
  {
    snprintf(mY_buffer, BUFFER_SIZE, "%s", MY_ARRAY[my_index].description);
  }

Проблема возникает в некоторых случаях, когда мне нужно вставить некоторые другие строки в строку при ее форматировании. Итак, я хочу что-то вроде этого (где описание в этом случае содержит %s).

void format_verbose_with_data(uint32_t my_index,
                              char     my_buffer[BUFFER_SIZE])
  {
    // ...
    snprintf(mY_buffer, BUFFER_SIZE, MY_ARRAY[my_index].description,
             some_string);
  }

Наш make-файл настроен так, чтобы это (опасное) использование snprintf() предупреждало, а предупреждения обрабатывались как ошибки. Значит, не скомпилируется. Я хотел бы отключить предупреждение только для этой строки, где, хотя это несколько опасно, я буду контролировать строку и могу проверить, работает ли она с каждым значением, с которым она вызывается.

В качестве альтернативы я был бы рад сделать это каким-то другим способом, но я действительно не хочу использовать это решение.

void format_verbose_with_data(uint32_t my_index,
                              char     my_buffer[BUFFER_SIZE])
  {
    // ...
    snprintf(mY_buffer, BUFFER_SIZE, "%s%s%s"
    MY_ARRAY[my_index].description1, some_string,
    MY_ARRAY[my_index].description2);
  }

Потому что это делает мой массив описания уродливым, особенно для тех, где мне не нужно добавлять дополнительные значения.


person Peter    schedule 27.08.2009    source источник


Ответы (3)


GCC не имеет возможности отключать предупреждения построчно, поэтому я подозреваю, что вам не повезло. И в любом случае, если ваши стандарты кодирования говорят, что вы не должны что-то делать, вы не должны искать способы победить их.

Еще один момент, когда вы говорите:

void format_verbose(uint32_t my_index,
                    char     my_buffer[BUFFER_SIZE])

вы действительно тратите свое время на набор текста - яснее и идиоматичнее сказать:

void format_verbose(uint32_t my_index,
                    char     my_buffer[])

or:

void format_verbose(uint32_t my_index,
                    char     * my_buffer)
person Community    schedule 27.08.2009
comment
Возможно, C не обеспечивает никакой защиты размера переданных буферов, но я не согласен с тем, что лучше не указывать размер буфера, когда вы ясно видите, что код предполагает, что он правильный. Ясность в глазах смотрящего :-) OTH, я, вероятно, должен защитить себя от коротких буферов, либо с определенным поведением ошибки, либо с утверждением. Примером проблемы со стандартом кодирования является приведение типов — мы разрешаем им предотвращать предупреждения компилятора, что делает происходящее более очевидным. - person Peter; 28.08.2009

Если все, что вы когда-либо делали с snprintf(), это копировало строки (что, кажется, имеет место), то есть все, что у вас когда-либо было, это одна или несколько "%s" в качестве строки формата, почему вы не используете strcpy(), возможно, с strlen() сначала проверить длину исходника?

Обратите внимание, что strncpy() хотя и выглядит как хорошая идея, таковой не является. Он всегда дополняет целевой буфер нулями, а в случае, если исходный размер превышает размер буфера, не завершает строку нулем.

person DevSolar    schedule 15.08.2014
comment
Спасибо за Ваш ответ! Я отказался от этой работы давным-давно :-(. Во всяком случае, я не уверен, что есть большая разница между двумя функциями. Скопируйте или распечатайте, я все еще хотел вставить что-то в середину строки, поэтому мне понравилось способ решения snprintf() в конечном итоге. - person Peter; 05.09.2014

После ночи размышлений я планирую вручную разделить входную строку, самостоятельно найдя маркер %s, а затем отправив строки по отдельности в snprintf() с их собственными %s. В этом случае, когда разрешен только 1 тип строки формата, это менее обременительно, однако было бы отстойно пытаться полностью заново реализовать анализатор стиля printf().

void format_verbose_with_data(uint32_t my_index,
                              char     my_buffer[BUFFER_SIZE])
  {
    char    pre_description[BUFFER_SIZE];
    char    post_description[BUFFER_SIZE];
    int32_t offset = -1;

    offset = find_string(MY_ARRAY[my_index].description, "%s");
    ASSERT(offset >=0, "No split location!");
    // Use offset to copy the pre and post descriptions
    // Exercise left to the reader :-)
    snprintf(mY_buffer, BUFFER_SIZE, "%s%s%s"
             pre_description, some_string, post_description);
  }
person Peter    schedule 27.08.2009
comment
Отредактировано, чтобы удалить глупую попытку проверить длину строкового буфера. Конечно, это не сработает, если только буфер не будет инициализирован полностью ненулевым. - person Peter; 28.08.2009