Почему GCC не создает предупреждение при назначении подписанного литерала для неподписанного типа?

Несколько вопросов на этом веб-сайте показывают, что при смешивании типов подписанных и неподписанных типов большинство компиляторов, похоже, хорошо справляются с созданием предупреждений этого типа. Однако GCC, похоже, не заботится о назначении подписанной константы неподписанному типу! Рассмотрим следующую программу:

/* foo.c */
#include <stdio.h>
int main(void)
{
    unsigned int x=20, y=-30;
    if (x > y) {
        printf("%d > %d\n", x, y);
    } else {
        printf("%d <= %d\n", x, y);
    }
    return 0;
}

Компиляция с GCC 4.2.1, как показано ниже, не выводит на консоль:

gcc -Werror -Wall -Wextra -pedantic foo.c -o foo

В результате исполняемый файл генерирует следующий вывод:

$ ./foo
20 <= -30

Есть ли какая-то причина, по которой GCC не генерирует предупреждения или сообщения об ошибке при назначении знакового значения -30 для целочисленной переменной без знака y?

Ответ 1

Используйте - Wconverersion:

~/src> gcc -Wconversion -Werror -Wall -Wextra -pedantic -o signwarn signwarn.c
cc1: warnings being treated as errors
signwarn.c: In function 'main':
signwarn.c:5: error: negative integer implicitly converted to unsigned type

Я предполагаю, что дело в том, что gcc действительно хорош в создании предупреждений, но по умолчанию он не делает этого для (иногда неожиданных) случаев. Это хорошая идея, чтобы просмотреть доступные предупреждения и выбрать набор параметров, которые генерируют те, которые, по вашему мнению, помогут. Или просто все, и отполируйте этот код, пока он не светит!:)

Ответ 2

Возможность преобразования отрицательного значения в неподписанный тип является особенностью языка C. По этой причине предупреждение не выдается по умолчанию. Вы должны запросить его явно, если хотите.

Что касается вывода вашей программы... Использование спецификатора формата %d printf с неподписанным значением, которое выходит за пределы диапазона типа int, приводит к поведению undefined, которое вы действительно наблюдаете в ваш эксперимент.

Ответ 3

Использование (без знака) -1 часто используется для установки всех битов, а иногда даже цитируется как причина для этой (неправильной) функции C, даже людьми, которые должны знать лучше , Это не очевидно и не переносимо - выражение, которое вы хотите использовать для установки всех битов, равно ~ 0.