2012-03-29 5 views
16

Я искал вокруг немного информации для этого, но не нашел ничего удовлетворительного. Есть ли какое-то особое поведение при вызове функцииПочему gcc -Wall предупреждает о строках формата нулевой длины?

sprintf(someString, ""); 

, что объясняет, почему это предупреждение (на gcc с -Wall)? Мне только удалось найти, что стандарт C допускает нулевые строки формата.

Я попытался следующий пример

#include <stdio.h> 

int main() 
{ 
    char str[2] = {'a', 'a'}; 
    sprintf(str, ""); 
    printf("\'%c\'\'%c\'\n", str[0], str[1]); 
    return 0; 
} 

, которая печатает

'''a' 

это именно то, что я ожидал увидеть. Итак, почему предупреждение?

+2

Я не понимаю, где вы обнаружили, что C++ не ... –

+1

Вы правы, я думал, что это было в первую очередь потому, что я компилировал код с g ++, но теперь я вижу, что gcc дает то же предупреждение. – SirGuy

+0

О, и в случае, если кому-то интересно, я случайно наткнулся на этот код, я сам его не написал – SirGuy

ответ

22

Тот факт, что сообщение GCC выдает предупреждение, обычно не имеет никакого отношения к тому, является ли конструкция законной C, но могут ли разработчики GCC считать это либо вероятным признаком того, что вы имели в виду нечто иное, чем то, что вы пишете, или просто плохой стиль. Вот некоторые примеры:

  • if (x = 0) - вы почти наверняка означало if (x == 0).
  • printf(str) - вы почти наверняка означали либо fputs(str, stdout), либо printf("%s", str); как написано, код очень опасен.
  • if (foo == bar & MASK) - Вы почти наверняка имели в виду if (foo == (bar & MASK)).

т.д.

В вашем случае, я думаю, что GCC спрашивает, почему вы звоните sprintf(String, ""), чтобы сделать эквивалент String[0]=0; (последний намного короче, быстрее и понятнее).

+1

Я согласен с тем, что было бы лучше, я просто не знаю, есть ли больше причин, чем это, если учесть это предупреждение. Я, конечно, не авторитет, но я не думал, что это конкретное преступление для разумного программирования было бы считаться заслуживающим внимания – SirGuy

+3

Я согласен, но GCC делает намного более раздражающие вещи с предупреждениями. Это, безусловно, меньшее преступление.Более крупный предупреждает о неиспользуемых аргументах функции, что неизбежно * всякий раз, когда вы используете указатели функций, которые должны соответствовать определенной сигнатуре. –

+0

Да, у меня никогда не было такого предупреждения, и у меня возникла такая ситуация. – SirGuy

4

Это просто предупреждение от GCC. Если вы хотите, чтобы подавить его для одной части вашего приложения, вы можете сделать следующее:

#pragma GCC diagnostic ignored "-Wformat-zero-length" 
int main() 
{ 
    // code that produces a warning 
} 
#pragma GCC diagnostic warning "-Wformat-zero-length" 
+1

Я знаю, что могу избавиться от него, мне было интересно, почему это было там, чтобы начать с – SirGuy

+5

Я думаю, что это просто бессмысленное, вредное предупреждение. Это может определенно укусить код, где строка формата равна либо нулевой, либо нетривиальной, в зависимости от определения/значения макроса препроцессора, и такой код кажется вполне разумным. –

+3

Это не опасно. Это просто дает вам знать, что в вашем коде есть что-то сомнительное, что вы допустили ошибку. Хотя 'sprintf (str," ");' является законным, это довольно крутой способ создания _str_ строки нулевой длины и может указывать на логическую ошибку в вашем коде. Это не запрещено; просто доведено до вашего сведения. –

6

Вы получаете предупреждение, потому что GCC знает, что второй аргумент sprintf() должен быть не пустая строка, как правило, один с различными спецификациями формата - функционально эквивалентный и «более законный» вызов тому, который вы делаете в коде, будет sprintf(str, "%s", ""). Кроме того, существует почти всегда один дополнительный N аргументов, достаточный для выполнения спецификаций формата. Поскольку вы используете его здесь, вы используете его как своего рода strcpy(), который, будучи технически обоснованным, является очень странным способом использования стандартной библиотеки.