#c #warnings
#c #предупреждения
Вопрос:
Я не знаю, откуда у меня эта привычка, но обычно я рассматриваю предупреждения компилятора как ошибки. Я знаю, что программа все равно будет работать, но предупреждения меня беспокоят. Тот, который, я думаю, ничего не значит для меня
Сужение преобразования из <тип данных> в <тип данных> определяется реализацией.
Я все еще пытаюсь это исправить. Итак, я пришел сюда, чтобы спросить, насколько срочно следует обрабатывать предупреждения компилятора? Я почти уверен, что многие из них будут отличаться, поэтому может кто-нибудь сказать мне, на какие из них обратить внимание?
Комментарии:
1. Это зависит от предупреждения и кода-нарушителя, но, как правило, рекомендуется писать код, который компилируется без предупреждений. Для получения бонусных очков вы можете выйти за рамки обычного уровня предупреждений, скомпилировав с
-Wall -Wextra -pedantic
.2. Зависит от ваших целей. Вы пишете программное обеспечение, о правильной работе которого заботитесь и планируете поддерживать? Вероятно, хорошая идея прослушать предупреждения. Если вы пишете быстрый сценарий, который не имеет значения, вы можете игнорировать их. Существует много предупреждений и много сценариев, поэтому трудно просто сказать «слушайте эти 5 и игнорируйте остальные».
Ответ №1:
Из-за долгой истории компиляторы C, как правило, выдают предупреждения для многих проблем, которые считаются ошибками на любых других языках. Стандарт C явно упоминает это как возможный результат в C11 / C18 5.1.1.3:
5.1.1.3 Диагностика
- Соответствующая реализация должна выдавать по крайней мере одно диагностическое сообщение (идентифицируемое способом, определенным реализацией), если блок предварительной обработки перевода или блок перевода содержит нарушение какого-либо синтаксического правила или ограничения, даже если поведение также явно указано как неопределенное или определенное реализацией. Диагностические сообщения не должны создаваться при других обстоятельствах. 9)
- ПРИМЕР Реализация должна выдать диагностику для блока перевода:
char i; int i;
поскольку в тех случаях, когда формулировка в этом международном стандарте описывает поведение конструкции как являющееся ошибкой ограничения и приводящее к неопределенному поведению, должна быть диагностирована ошибка ограничения.
Сноски
- Цель состоит в том, чтобы реализация определяла характер и, по возможности, локализовала каждое нарушение. Конечно, реализация может производить любое количество диагностик, если действующая программа все еще правильно переведена. Он также может успешно перевести недопустимую программу.
(выделение мое)
Поэтому сам факт успешной компиляции программы не может рассматриваться как доказательство того, что она не делает что-то глубоко неправильное в C. Например, многие неопределенные варианты поведения имеют тенденцию изменять поведение в одном и том же компиляторе в зависимости от параметров командной строки.
Компиляторы C все еще настолько консервативны, что к любым предупреждениям, выдаваемым по умолчанию, следует относиться серьезно и тщательно исследовать.
Не вся диагностика включена по умолчанию. Например, в GCC есть два широких переключателя категорий:
-Стена
Это позволяет удалять все предупреждения о конструкциях, которые некоторые пользователи считают сомнительными, и которые легко избежать (или изменить, чтобы предотвратить предупреждение), даже в сочетании с макросами. Это также позволяет использовать некоторые зависящие от языка предупреждения, описанные в параметрах диалекта C и Objective-C и Objective-C
-Wextra
Это включает некоторые дополнительные флаги предупреждения, которые не включены по умолчанию.
As -Wall
упоминает сомнительные конструкции, которые он диагностирует, было бы легко избежать или изменить. -Wextra
добавляет диагностику для более стилистических проблем, таких как «неиспользуемая переменная», которая время от времени высвечивает реальные проблемы в вашем коде — возможно, вы должны были использовать эту переменную j
, но опечатали ее в коде или забыли умножить на нее…
Мое субъективное, но экспертное мнение заключается в том, что если
- Компилятор выдает предупреждения даже без
-Wall -Wextra
определенных параметров предупреждения, я бы даже не запускал его для целей отладки. - Я бы не стал использовать код в рабочей среде без анализа каждого из предупреждений, созданных
-Wall -Wextra
. Конечно, этот процесс будет проще, если вы исправите эти проблемы, поскольку количество диагностических сообщений уменьшится.
В случае
Сужение преобразования из в определяется реализацией.
это диагностическое сообщение, скорее всего, не включено по умолчанию. Это говорит о том, что операция, подобная
int i;
float f = i;
предпринята попытка и что преобразование должно отличаться по поведению от реализации к другой. Обычно средства реализации (компилятор, операционная система, процессор) — так что, если вы ознакомились с руководствами по компиляции и нашли задокументированное там поведение, определяемое реализацией, приемлемым, то, конечно, допустимо подавить его тем или иным способом.
Если на данный момент вы нацелены на ту же операционную систему, используете тот же компилятор или компилятор с аналогичным поведением (GCC / Clang) и то же семейство процессоров, все равно, вероятно, лучше просто подавить эти диагностики поведения, определенного реализацией, с помощью переключателя командной строки, а не добавлять приведения в кодечтобы просто подавить возможную проблему переносимости. Таким образом, если вам нужно просмотреть их для переноса на новую реализацию, вы можете повторно включить предупреждение.
С другой стороны, есть предупреждения, которые сигнализируют о неопределенном поведении:
x.c: In function ‘main’:
x.c:5:22: warning: right shift count >= width of type
[-Wshift-count-overflow]
5 | printf("%dn", a >> 33);
| ^~
или
x.c: warning: iteration 2147483647 invokes undefined behavior
[-Waggressive-loop-optimizations]
8 | for (i = 0; i >= 0; i ) { }
| ~^~
(будет диагностироваться GCC только при включенной оптимизации)
или
x.c:5:14: warning: format ‘%f’ expects argument of type ‘double’,
but argument 2 has type ‘int’ [-Wformat=]
5 | printf("%fn", i);
| ~^ ~
| | |
| | int
| double
| %d
Они действительно говорят о серьезных ошибках кодирования, последствия которых может быть очень сложно отладить — и поведение одной и той же конструкции может различаться даже в пределах одного и того же скомпилированного исполняемого файла, не говоря уже о разных процессорах. Лично я бы даже не стал запускать программу даже в целях тестирования, пока не исправил бы их.