Итак, я снова прочитал официальную документацию с предупреждением C4310 и нашел ключевое слово: cast и truncate .
Очевидно, MSVC считает, что преднамеренное приведение является непреднамеренным усечением .Как так?Давайте посмотрим на официальный пример.
long int a;
a = (char) 128; // C4310, use value 0-127 to resolve
Для MSVC char
подписано по умолчанию.Поскольку значение signed char
колеблется от -128 до 127, когда компилятор увидел, что кто-то пытается преобразовать 128
как char
, что, несомненно, приведет к совершенно другому значению -128
, компилятор выдаст предупреждение C4310, посколькуприведение выглядит как ошибка.
Однако, если вы удалите приведение и непосредственно назначите значение char
вместо этого:
char c = 128; // warning?
Вы можете подумать, что, поскольку MSVC умно предупреждаетпрограммист о сомнительном кастинге, наверняка он выдаст большее предупреждение на этот раз.К сожалению, это не так.Я повторяю, не будет выдавать никаких предупреждений .
Так что, если вы допустите ошибку, инициализируйте переменную signed
положительным целочисленным значением, которое может быть представлено только unsigned
, MSVC будетне предупреждаю вас.MSVC предупредит вас, только если вы инициализируете значением, которое не может обработать даже версия unsigned
типа данных.
char c = 255; // no warning
char c = 256; // warning: truncation from 'int' to 'char'
Или если вы действительно хотите, чтобы MSVC проверил это за вас, вам нужно привести.
char c = (char)128; // MSVC emits C4310
Таким образом, я считаю C4310 бесполезным и, возможно, вредным.Кажется, это поощряет программиста на C не разыгрывать вещи, которые должны быть разыграны.Потому что, если вы разыгрываете, это предупреждает.Если вы не сыграете, это не предупредит.Так зачем разыгрывать, когда вы можете уйти без кастинга?Это смешно ИМХО.
В GCC ситуация меняется на противоположную.В ролях?Нет предупрежденияНет актеров?Издайте предупреждение.Это так просто.
Таким образом, если вы пытаетесь написать подобный код, который компилируется без предупреждения под обоими компиляторами, вы попадаете в шахматную ситуацию, как гласит заголовок этого вопроса, GCC предупреждает безприведение, в то время как MSVC предупреждает с приведением .Добро пожаловать на территорию, несовместимую с компилятором.
Bouns
Найдите минимальное значение, которое может содержать произвольный целочисленный тип со знаком безпредупреждение от обоих компиляторов, без uintmax_t
.
typedef short rInt;
rInt const rIntMin = (rInt)-1 << (sizeof(rInt) * CHAR_BIT - 1);
Как это работает?Возьмем, например, 16-битный код, код превращается с 1111 1111 1111 1111
в 1000 0000 0000 0000
.Поскольку целочисленное значение является отрицательным до сдвига битов, а также отрицательным после сдвига битов, операция считается безопасной, поэтому предупреждение от обоих компиляторов отсутствует.