Предупреждение: переполнение в неявном постоянном преобразовании

В следующей программе строка 5 дает предупреждение о переполнении, как ожидалось, но удивительно, что строка 4 не дает никаких предупреждений в GCC: http://www.ideone.com/U0BXn

int main()
{
    int i = 256;
    char c1 = i;    //line 4
    char c2 = 256;  //line 5
    return 0;
}

Я думал, что обе строки должны давать предупреждение о переполнении. Или что-то мне не хватает?


Тема, которая привела меня к этому эксперименту, такова: проверка типа typedef?

Там я сказал следующее (которое я удалил из своего ответа, потому что, когда я его запускал, он не отображался, как я и ожидал):

//However, you'll get warning for this case:

typedef int  T1;
typedef char T2;

T1 x = 256;     
T2 y = x; //possible overflow warning! (but it doesn't give warning :()

Ответ 1

-Wall не содержит много параметров. -Wconversion является одним из них и предупреждает о поведении, которое вас интересует.

См. http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html

Ответ 2

В общем случае присвоения значения int объекту char компилятор не знает, находится ли int вне диапазона char.

Внимательно посмотрите на фактическое предупреждение:

warning: overflow in implicit constant conversion

В этом конкретном случае, когда константа преобразуется в char, что компилятор может вас предупредить. Аналогично, если вы изменили объявление i на const:

const int i = 256;

вы также получите предупреждение, потому что значение, присвоенное c2, является константным выражением.

Обратите также внимание, что предупреждение несколько вводит в заблуждение, поскольку преобразование технически не "переполняется". Арифметическое переполнение дает поведение undefined в С++. Сужение преобразования (например, int to char, если int имеет больший диапазон, чем char), дает некоторое преобразование, определенное реализацией.

Ответ 3

Ну, строка 5 - очевидная ошибка, которую может видеть любой компилятор напрямую, и всегда ошибка. Для обнаружения ошибки для строки 4 потребуется не менее некоторый анализ потока данных. Возможно, это не сделано с настройками, используемыми на сайте, или, возможно, авторы компилятора не считают это достаточно важным, чтобы понять это.

Ответ 4

Опубликовать GCC 4.3, семантика -Wconversion была обновлена, чтобы обнаружить неявные преобразования, которые могут изменить значение, но вам также нужно включить -Wsign-conversion, потому что в противном случае вы не получите предупреждение для кода, который может изменить знак числа из-за принуждения между подписанными и неподписанными типами.

В отличие от того, что говорит Crazy Eddie, до GCC 4.3 (который еще не был выпущен в то время) -Wconversion не проверил в целом проблемы, вызванные неявным преобразованием типа и т.п. Скорее, он проверил, будет ли ваша программа вести себя иначе, чем это было бы, если бы она использовала прототипы функции K & R старого стиля.

Это не только означало, что оно не давало предупреждения о всех неявных проблемах преобразования/принуждения типа, но это также означало, что некоторый хороший код дал ненужное предупреждение. И, конечно же, вы не получите ошибки с g++, потому что такие прототипы в любом случае недействительны С++.