C - беззнаковое целое становится отрицательным (-ve)

Что я знаю, так это то, что UNSIGNED INT не может принимать отрицательные значения.
Если я возьму maximum value из UNSIGNED INT и увеличу его, я должен получить ZERO, то есть minimum value, а если я возьму minimum value и уменьшу его, я должен получить maximum value.
Тогда почему это происходит?

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

int main()
{
    unsigned int ui;
    ui = UINT_MAX;
    ui ++;
    printf("ui = %d", ui);

    ui = 0;
    ui --;
    printf("\n");
    printf("ui = %d", ui);

    return EXIT_SUCCESS;
}

Вывод:

ui = 0
ui = -1

person Community    schedule 05.03.2015    source источник
comment
это из-за переполнения int   -  person sashas    schedule 05.03.2015
comment
%d ? разве это не должно быть %u ?   -  person WhozCraig    schedule 05.03.2015
comment
Я должен прочитать спецификацию, чтобы быть уверенным, но IIRC либо переполнение, либо недополнение, скорее всего, неопределенное поведение.   -  person Some programmer dude    schedule 05.03.2015
comment
%d говорит рассматривать его как целое число, и это так.   -  person Retired Ninja    schedule 05.03.2015
comment
C11 6.2.5/9: Вычисление, включающее операнды без знака, никогда не может переполниться, потому что результат, который не может быть представлен результирующим целочисленным типом без знака, уменьшается по модулю числа, которое на единицу больше, чем наибольшее значение, которое может быть представлено результирующий тип.   -  person Lundin    schedule 05.03.2015


Ответы (4)


Вы передаете значение функции с многоточием (printf). Вы не должны ожидать ничего о подписи здесь.

%d в строке формата управляет знаком отображаемого значения. Внутри функции printf есть приведение, так как вы выбрали функцию %d. Вот почему вы видите значение signed, эквивалентное двоичному значению FFFFFFFF1.

1 Предполагается, что ширина целого числа составляет 32 бита.

person harper    schedule 05.03.2015
comment
Отличное объяснение! Спасибо :) - person ; 05.03.2015

Из 'man 3 printf':

d, i Аргумент int преобразуется в десятичную запись со знаком.

Таким образом, хотя тип ui равен unsigned int, printf интерпретирует его как signed int и показывает как таковой.

person John O'M.    schedule 05.03.2015

Это потому, что вы используете спецификатор формата %d, который говорит printf для обработки вашего числа как целого числа со знаком. Попробуйте использовать %u для вывода значения без знака, и вы получите желаемый результат.

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>

int main()
{
    unsigned int ui;
    ui = UINT_MAX;
    ui ++;
    printf("ui = %u", ui);
    ui = 0;
    ui --;
    printf("\n");
    printf("ui = %u", ui);
    return EXIT_SUCCESS;
}

вывод:

ui = 0
ui = 4294967295

Ознакомьтесь с справочником по возможным спецификаторам формата.

person Max Komarychev    schedule 05.03.2015

printf("%u") следует использовать для unsigned ints.

person Joakim Ericsson    schedule 05.03.2015