Это довольно важное предупреждение, которое не только отключено по умолчанию, но и отключено даже при большинстве способов включения предупреждений на практике.
Что ж, авторы g cc не согласны с вами, и они объяснили, почему в руководстве:
-Wwrite-strings
При компиляции C укажите строковые константы введите const char[length]
, чтобы при копировании адреса адреса в не const
char *
указывалось предупреждение. Эти предупреждения помогут вам найти во время компиляции код, который может попытаться записать в строковую константу, но только если вы очень внимательно относились к использованию const
в объявлениях и прототипах. В противном случае это просто неприятность. Вот почему мы не заставили -Wall
запросить эти предупреждения.
Это также объясняет ваш второй вопрос: вывод
G CC относится к -Wdiscarded-qualifiers, но если я передам это вместо - Записать строки, я не получаю это предупреждение.
Потому что без -Wwrite-strings
строковый литерал просто имеет тип char[]
, поэтому ни один классификатор не отбрасывается.
(Это также объясняет, почему в сообщении упоминается -Wdiscarded-qualifiers
вместо -Wwrite-strings
; проблема на самом деле в отбрасываемом квалификаторе, и код предупреждения для этого не возвращает вас к сообщению, что единственная причина была Во-первых, квалификатор был из-за другого варианта. Это было бы ужасно сложно.)
Я думал, что все означало «буквально каждое предупреждение, о котором знает компилятор», но это, кажется, противоречит что.
Да, это то, о чем говорится в руководстве clang:
В дополнение к традиционным флагам -W, можно включить всю диагностику мимоходом Это работает, как и ожидалось, с -Werror, а также включает предупреждения от -pedanti c.
Действительно, это уже было зарегистрировано как ошибка: https://bugs.llvm.org/show_bug.cgi?id=18801. Очевидно, -Weverything
включил это предупреждение в clang 3.4 и более ранних версиях, но произошла регрессия или преднамеренное изменение, которое не было задокументировано. Eri c Ответ Постписила дает правдоподобную причину, по которой он мог быть преднамеренным: он не только включает предупреждение, но и фактически изменяет языковой диалект.
Если я компилирую тот же код, что и C ++, вместо C, тогда и G CC, и Clang выдают мне предупреждение, которое я хочу, без необходимости использования каких-либо флагов компилятора. Я не уверен, почему здесь есть разница между языками, так как AFAIK, и C и C ++ имеют неопределенное поведение, если вы действительно пишете в строковый литерал.
В C ++ (очевидно, так как C ++ 11) тип строкового литерала фактически определяется языком как const char[]
, тогда как в стандартном C это всегда был просто char []
, в который вы не должны писать. См. Каков тип строковых литералов в C и C ++?