как я могу присвоить значение> 127
Результатом преобразования целочисленного значения вне диапазона в целочисленный тип со знаком является либо результат, определенный реализацией, либо реализация-определенный сигнал (6.3.1.3/3).Таким образом, ваш код является допустимым C, он просто не имеет одинакового поведения во всех реализациях.
без получения предупреждения о переполнении
Решать GCC должен полностьюстоит ли предупреждать или нет о действительном коде.Я не совсем уверен, каковы его правила, но я получаю предупреждение за инициализацию signed char
с 256
, но не с 255
.Я предполагаю, что это потому, что предупреждение для кода типа char a = 0xFF
обычно не требуется программисту, даже если char подписан.Существует проблема переносимости, связанная с тем, что тот же код на другом компиляторе может вызвать сигнал или привести к значению 0
или 23
.
-pedantic
включает предупреждение об этом (спасибо, pmg), что имеет смысл, поскольку -pedantic
предназначен для помощи в написании переносимого кода.Или, возможно, не имеет смысла, поскольку, как указывает R .., это выходит за рамки простого перевода компилятора в режим стандартного соответствия.Однако на странице руководства для gcc сказано, что -pedantic
включает диагностику, требуемую стандартом.Это не так, но на странице руководства также написано:
Некоторые пользователи пытаются использовать -pedantic для проверки программ на предмет строгого соответствия ISO C.Вскоре они обнаруживают, что он делает не совсем то, что им нужно: он находит некоторые практики, отличные от ISO, но не все - только те, для которых ISO C требует диагностики, и некоторые другие, для которых диагностика была добавлена.
Это заставляет меня задуматься о том, что такое "практика, отличная от ISO", и подозревать, что char a = 255
является одним из тех случаев, для которых диагностика была специально добавлена.Конечно, «не-ISO» означает больше, чем просто вещи, для которых стандарт требует диагностики, но gcc, очевидно, не заходит так далеко, чтобы диагностировать весь не строго соответствующий код такого типа.
Я также получаюпредупреждение для инициализации int
с ((long long)UINT_MAX) + 1
, но не с UINT_MAX
.Похоже, что по умолчанию gcc последовательно дает вам первую степень 2 бесплатно, но после этого он думает, что вы допустили ошибку.
Используйте -Wconversion
, чтобы получить предупреждение обо всех этих инициализациях, включаяchar a = 255
.Остерегайтесь, это даст вам множество других предупреждений, которые вы можете или не хотите.
вся эта неявность не облегчит понимание
Вы будетеЯ должен обсудить это с Деннисом Ричи.C слабо типизирован в отношении арифметических типов.Все они неявно преобразуются друг в друга с различными уровнями плохого поведения, когда значение выходит за пределы диапазона в зависимости от используемых типов.Опять же, -Wconversion
предупреждает об опасных.
Есть и другие конструктивные решения в C, которые означают, что слабость очень важна, чтобы избежать громоздкого кода.Например, тот факт, что арифметика всегда выполняется по крайней мере в int
, означает, что char a = 1, b = 2; a = a + b
включает в себя неявное преобразование из int
в char
, когда результат сложения присваивается a
.Если вы используете -Wconversion
, или если у C вообще не было неявного преобразования, вы должны написать a = (char)(a+b)
, что не было бы слишком популярно.В этом отношении char a = 1
и даже char a = 'a'
являются неявными преобразованиями из int
в char
, поскольку в C нет литералов типа char
.Так что, если бы не все эти неявные преобразования, либо разные другие части языка должны были бы быть разными, иначе вам пришлось бы полностью засорять ваш код приведениями.Некоторые программисты хотят строгой типизации, что достаточно справедливо, но вы не получаете ее в C.