Вопрос:

Присваивание отрицательных чисел неподписанному int?

c

88561 просмотра

14 ответа

5733 Репутация автора

В языке программирования C unsigned intиспользуется для хранения только положительных значений. Тем не менее, когда я запускаю следующий код:

unsigned int x = -12;
printf("%d", x);

Выход по-прежнему -12. Я думал, что это должно было распечатать: 12, или я что-то неправильно понимаю?

Автор: ipkiss Источник Размещён: 02.03.2011 03:30

Ответы (14)


4 плюса

28517 Репутация автора

printf('%d', x); 

Означает печатать целое число со знаком. Вы должны будете написать это вместо этого:

printf('%u', x);

Кроме того, он по-прежнему не будет печатать «12», это будет «4294967284».

Автор: Linus Kleen Размещён: 02.03.2011 03:34

17 плюса

72079 Репутация автора

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

Автор: Erik Размещён: 02.03.2011 03:34

2 плюса

6909 Репутация автора

Чего вам не хватает, так это того, что printf ("% d", x) ожидает, что x будет подписан, поэтому, хотя вы назначаете -12 для x, это интерпретируется как дополнение к 2, что будет очень большим числом. Однако, когда вы передаете это действительно большое число в printf, оно интерпретирует его как подписанное, что корректно переводит его обратно в -12.

Правильный синтаксис для печати без знака в print f - «% u» - попробуйте это и посмотрите, что он делает!

Автор: Elemental Размещён: 02.03.2011 03:35

3 плюса

320636 Репутация автора

Они хранят положительные значения. Но вы выводите (очень высокое) положительное значение в виде целого числа со знаком, поэтому оно снова интерпретируется (я бы добавил, в зависимости от реализации).

"%uВместо этого используйте флаг формата .

Автор: Lightness Races with Monica Размещён: 02.03.2011 03:35

30 плюса

41336 Репутация автора

Int не имеет значения, но вы сказали printfсмотреть на него как на подписанное int.

Пытаться

unsigned int x = -12; printf("%u", x);

Он не будет печатать «12», но будет печатать максимальное значение без знака int минус 11.

Упражнение для читателя, чтобы узнать, почему :)

Автор: Binary Worrier Размещён: 02.03.2011 03:36

1 плюс

58930 Репутация автора

Присваивание отрицательного значения int без знака не вычисляет абсолютное значение отрицания: оно интерпретирует как беззнаковое int двоичное представление отрицательного значения, т. Е. 4294967284 (2 ^ 32 - 12).

printf ("% d") выполняет противоположную интерпретацию. Вот почему ваша программа отображает -12.

Автор: mouviciel Размещён: 02.03.2011 03:44

7 плюса

21271 Репутация автора

Все это связано с интерпретацией стоимости.

Если вы предполагаете 16-битные целые числа со знаком и без знака, то вот несколько примеров, которые не совсем верны, но демонстрируют концепцию.

0000 0000 0000 1100 целое число без знака и целое число со знаком 12

1000 0000 0000 1100 целое число со знаком -12 и большое целое число без знака.

Для целых чисел со знаком бит слева является битом знака. 0 = положительный 1 = отрицательный

Для целых чисел без знака бит знака отсутствует. бит левой руки, позволяет хранить большее число вместо.

Поэтому причина, по которой вы не видите того, чего ожидаете, заключается в том, что

unsigned int x = -12, принимает -12 как целое число и сохраняет его в x. x без знака, так что то, что было знаковым битом, теперь является частью значения.

printf позволяет вам сообщить компилятору, как вы хотите, чтобы значение отображалось.

% d означает отображать его так, как если бы он был подписанным int. % u означает отображать его так, как если бы он был беззнаковым целым.

С позволяет вам делать такие вещи. Вы программист в контроле.

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

один, возможно, полезный случай заключается в следующем

без знака int allBitsOn = -1;

Это конкретное значение устанавливает все биты в 1

1111 1111 1111 1111

это может быть полезно иногда.

Автор: EvilTeach Размещён: 02.03.2011 03:46

62 плюса

652 Репутация автора

Решение

-12Справа от вашего знака равенства устанавливаются как целое число (вероятно , 32 бита в размере) и будет иметь шестнадцатеричное значение 0xFFFFFFF4. Компилятор генерирует код для перемещения этого целого числа со знаком в ваше целое число без знака, xкоторое также является 32-битным объектом. Компилятор предполагает, что у вас есть только положительное значение справа от знака равенства, поэтому он просто перемещает все 32 бита в x. xтеперь имеет значение, 0xFFFFFFF4которое 4294967284интерпретируется как положительное число. Но printfформат %dговорит, что 32 бита следует интерпретировать как целое число со знаком, так что вы получите -12. Если бы вы использовали %uэто напечатало бы как 4294967284.

В любом случае вы не получите того, что ожидали, поскольку язык C «доверяет» автору кода, чтобы он запрашивал только «разумные» вещи. Это общепринятая в С. Если вы хотите присвоить значение xи не были уверены в том , был положительным вы могли бы написать значение на правой стороне равенства unsigned int x = abs(-12);и заставил компилятор генерировать код для вычисления абсолютного значения целого числа перед перемещением в целое число без знака.

Автор: Tim Oltrogge Размещён: 02.03.2011 03:57

0 плюса

44 Репутация автора

Когда компилятор неявно преобразует -12 в целое число без знака, базовое двоичное представление остается неизменным. Это преобразование чисто семантическое. Знаковый бит целого числа дополнения двух становится самым значимым битом целого числа без знака. Таким образом, когда printf рассматривает целое число без знака как целое число со знаком с% ​​d, он будет видеть -12.

Автор: Faust Размещён: 02.03.2011 05:44

3 плюса

166975 Репутация автора

Ваша программа имеет неопределенное поведение, потому что вы передали неправильный тип printf(вы сказали, что собираетесь передать, intно передали unsigned int). Считай, что тебе повезло, что самой простой вещью для реализации было просто тихо вывести неправильное значение и не переходить к какому-либо коду, который делает что-то вредное ...

Автор: R.. Размещён: 02.03.2011 09:04

0 плюса

58 Репутация автора

В общем контексте, когда могут храниться только положительные числа, отрицательные числа не сохраняются в явном виде, но их дополнение к 2 сохраняется. Таким же образом здесь, дополнение 2 к -12 будет храниться в «х», и вы используете его, %uчтобы получить его.

Автор: King Размещён: 30.01.2012 06:32

1 плюс

11 Репутация автора

int и unsigned int используются для выделения количества байтов для хранения значения, ничего более.

Компилятор должен выдавать предупреждения о несоответствии со знаком, но это действительно не влияет на биты в памяти, которые представляют значение -12.

% x,% d,% u и т. д. говорит компилятору, как прервать количество битов при их печати.

Автор: trevor Размещён: 16.08.2014 05:07

1 плюс

11 Репутация автора

Когда вы пытаетесь отобразить значение int, вы передаете его аргументу (int), а не аргументу (unsigned int), и это приводит к выводу -12, а не 4294967284. Целые числа хранятся в шестнадцатеричном формате и -12 для int то же самое, что 4294967284 для unsigned int в шестнадцатеричном формате. Вот почему "% u" печатает нужное вам значение, а не "% d" .. Это зависит от типа вашего аргумента .. УДАЧИ!

Автор: Vern01 Размещён: 24.05.2016 01:08

1 плюс

11 Репутация автора

-12 в 16-битном формате 2-х комплиментов. Сделайте так: if (x & 0x8000) {x = ~ x + 1; } Это преобразует число -ve комплимента 2 в эквивалентное число + ve. Удачи.

Автор: Nichola Tesla Размещён: 11.10.2018 10:50
Вопросы из категории :
32x32