Присвоение отрицательных чисел беззнаковому int?
на языке программирования C,unsigned int используется только для хранения положительных значений. Однако, когда я запускаю следующий код:
unsigned int x = -12;
printf("%d", x);
выход по-прежнему -12. Я думал, что он должен был распечатать: 12, или я что-то неправильно понял?
13 ответов:
The
-12справа от знака равенства задается как целое число со знаком (наверное, 32 бита в размер) и будет иметь шестнадцатеричное значение0xFFFFFFF4. Компилятор генерирует код для перемещения этого целого числа со знаком в ваше целое число без знакаxчто также является 32-разрядной организацией. Компилятор предполагает, что у вас есть только положительное значение справа от знака равенства, поэтому он просто перемещает все 32 бита вx.xтеперь имеет значение0xFFFFFFF4что это4294967284если интерпретируется как положительный число. Но это на%dговорит, что 32 бита должны быть интерпретированы как целое число со знаком, так что вы получите-12. Если бы вы использовали%uон бы напечатал как4294967284.в любом случае вы не получите то, что ожидали, так как язык C "доверяет" автору кода только просить "разумные" вещи. Это часто встречается в C. Если вы хотите присвоить значение
xи не были уверены, что значение в правой части равных было положительным, вы могли бы иметь написаноunsigned int x = abs(-12);и заставил компилятор генерировать код, чтобы принять абсолютное значение целого числа со знаком, прежде чем переместить его в целое число без знака.
int не Спет, но вы сказали
printfчтобы посмотреть на него как на подписанный int.попробовать
unsigned int x = -12; printf("%u", x);Он не будет печатать "12", но будет печатать максимальное значение без знака int минус 11.
упражнение для читателя, чтобы узнать, почему :)
передача %d в printf указывает printf рассматривать аргумент как целое число со знаком, независимо от того, что вы на самом деле передаете. Используйте %u для печати без знака.
все это имеет отношение к интерпретации значения.
Если вы предполагаете 16-битные знаковые и беззнаковые целые числа, то вот некоторые примеры, которые не совсем корректны, но демонстрируют концепцию.
0000 0000 0000 1100 unsigned int и signed int значение 12
1000 0000 0000 1100 значение int со знаком -12 и большое целое число без знака.
для целых чисел со знаком бит слева является битом знака. 0 = положительное 1 = отрицательно
для целых чисел без знака не существует знакового бита. левый бит, позволяет хранить большее число вместо этого.
Так почему вы не видите, что вы ожидаете это.
unsigned int x = -12, принимает -12 как целое число и сохраняет его в x. x без знака, поэтому то, что было знаковым битом, теперь является частью значения.
функции printf позволяет сообщить компилятору, как вы хотите, чтобы значение, которое будет отображаться.
%d означает отображать его как если бы это был подписанный int. %u означает отображать его так, как если бы это был неподписанный int.
c позволяет вам делать такие вещи. Вы программист находитесь в управлении.
вроде как огнестрельное оружие. Это инструмент. Вы можете использовать его правильно, чтобы справиться с определенными ситуациями, или неправильно убрать один из пальцев ноги.
одним из возможных полезных случаев является следующее
unsigned int allBitsOn = -1;
Это конкретное значение устанавливает все биты 1
1111 1111 1111 1111
Что может быть полезно иногда.
printf('%d', x);означает вывод целого числа со знаком. Вам придется написать это вместо:
printf('%u', x);кроме того, он все равно не будет печатать "12", это будет "4294967284".
они хранят положительные значения. Но вы выводите (очень высокое) положительное значение как целое число со знаком, поэтому оно снова интерпретируется (я мог бы добавить, что это определяется реализацией).
используйте флаг формата .
ваша программа имеет неопределенное поведение, потому что вы передали неправильный тип
printf(вы сказали ему, что собираетесь пройтиintно вы прошлиunsigned int). Считайте, что вам повезло, что" самая простая " вещь для реализации-это просто молча напечатать неправильное значение и не перейти к какому-то коду, который делает что-то вредное...
вам не хватает того,что printf("%d", x) ожидает, что x будет подписан, поэтому, хотя вы назначаете -12 x, он интерпретируется как дополнение 2, которое будет очень большим числом. Однако, когда вы передаете это действительно большое число в printf, он интерпретирует его как подписанный, таким образом, правильно переводя его обратно в -12.
правильный синтаксис для печати без знака в print f- "%u " - попробуйте это и посмотрите, что он делает!
присвоение отрицательного значения беззнаковому int не вычисляет абсолютное значение отрицательного: оно интерпретирует как беззнаковое int двоичное представление отрицательного значения, т. е., 4294967284 (2^32 - 12).
printf ("%d") выполняет противоположную интерпретацию. Вот почему ваша программа показывает -12.
когда вы пытаетесь отобразить значение int, вы передаете его в аргумент (int), а не в аргумент (unsigned int), и это заставляет его печатать -12, а не 4294967284. целые числа хранятся в шестнадцатеричном формате и -12 для int-это то же самое, что 4294967284 для unsigned int в шестнадцатеричном формате.. Вот почему "%u "печатает нужное значение, а не"%d".. Это зависит от типа аргумента..УДАЧИ ВАМ!
когда компилятор неявно преобразует -12 в целое число без знака, базовое двоичное представление остается неизменным. Это преобразование является чисто семантическим. Знаковый бит целого числа дополнения двух становится наиболее значимым битом целого числа без знака. Таким образом, когда printf обрабатывает целое число без знака как целое число со знаком %d, он увидит -12.
В общем контексте, когда могут быть сохранены только положительные числа, отрицательные числа не сохраняются явно, но их дополнение 2 сохраняется. Таким же образом здесь, дополнение 2 из -12 будет храниться в "x", и вы используете
%uчтобы получить его.
int и unsigned int используются для выделения количества байтов для хранения значения не более.
компилятор должен выдавать предупреждения о несоответствии подписей, но это действительно не влияет на биты в памяти, которые представляют значение -12.
%x, %d, %u и т. д. сообщает компилятору, как прервать ряд битов при их печати.
Comments