Почему GCC не выдает предупреждение при назначении литерала со знаком типу без знака? - PullRequest
14 голосов
/ 05 мая 2010

Несколько вопросов на этом сайте показывают подводные камни при смешивании типов со знаком и без знака, и большинство компиляторов, похоже, хорошо справляются с генерацией предупреждений этого типа. Тем не менее, 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?

Ответы [ 3 ]

21 голосов
/ 05 мая 2010

Использование -Wconversion :

~/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 на самом деле довольно хорошо генерирует предупреждения, но по умолчанию не делает этого для (иногда неожиданных) случаев. Это хорошая идея, чтобы просмотреть доступные предупреждения и выбрать набор опций, которые сгенерируют те, которые, по вашему мнению, могли бы помочь. Или просто все они, и отполируйте этот код, пока он не засияет! :)

7 голосов
/ 05 мая 2010

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

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

2 голосов
/ 18 августа 2016

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

...