Присвойте отрицательное число целому без знака - PullRequest
1 голос
/ 21 мая 2019

Этот код дает значимый вывод

#include <iostream>

int main() {
    unsigned int ui = 100;
    unsigned int negative_ui = -22u;

    std::cout << ui + negative_ui << std::endl;

}

Выход:

78

Переменная negative_ui хранит -22, но является unsigned int. У меня вопрос, почему unsigned int negative_ui = -22u; работает. Как unsigned int может хранить отрицательное число? Это сохранить для использования или это приводит к неопределенному поведению?

Я использую компилятор intel 18.0.3. С опцией -Wall предупреждений не было.

Ps. Я прочитал Что произойдет, если я назначу отрицательное значение переменной без знака? и Почему в unsigned int содержится отрицательное число

Ответы [ 2 ]

8 голосов
/ 21 мая 2019

Как unsigned int может хранить отрицательное число?

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

Сохраняется ли использование или это приводит к неопределенному поведению?

Нет UB. Un хорошо выражено арифметическое переполнение со знаком.

На результат можно положиться.Тем не менее, это может быть хрупким.Например, если вы добавите -22u и 100ull, тогда вы получите UINT_MAX + 79 (то есть большое значение, предполагая, что unsigned long long - это больший тип, чем unsigned), что соответствует 78 по модулю UINT_MAX + 1, которое представимов unsigned long long, но не представляется в unsigned.

Обратите внимание, что знаковое арифметическое переполнение равно не определено.

1 голос
/ 21 мая 2019

Подпись / Подпись - это соглашение.Он использует последний бит переменной (в случае x86 int - последний 31-й бит).То, что вы сохраняете в переменной, занимает полную битовую длину.

Это следующие вычисления, которые принимают старший бит в качестве индикатора знака или игнорируют его.Поэтому любая «беззнаковая» переменная может содержать значение со знаком, которое будет преобразовано в форму без знака, когда переменная без знака участвует в вычислении.

unsigned int x = -1; // x is now 0xFFFFFFFF.  
x -= 1; //  x is now 0xFFFFFFFE. 
if (x < 0) // false. x is compared as 0xFFFFFFFE.

int x = -1; // x stored as 0xFFFFFFFF
x -= 1; // x stored as 0xFFFFFFFE
if (x < 0) // true, x is compared as -2.

Технически допустимое, плохое программирование.

...