Реальная разница между "int" и "unsigned int"
Int
32-разрядный тип данных int может хранить целые значения в диапазоне
-2,147,483,648 до 2,147,483,647. Вы также можете обратиться к этому типу данных
как подписанный int или подписанный.
unsigned int:
32-битные беззнаковые данные int
тип может содержать целые значения в диапазоне от 0 до 4 294 967 295. Вы
также может ссылаться на этот тип данных просто как unsigned.
Хорошо, но на практике:
int x = 0xFFFFFFFF;
unsigned int y = 0xFFFFFFFF;
printf("%d, %d, %u, %u", x, y, x, y);
// -1, -1, 4294967295, 4294967295
нет разницы, О. Я немного смущен.
Ответы
Ответ 1
Хех. У вас есть неявный бросок здесь, потому что вы говорите printf
, какого типа ожидать.
Попробуйте это вместо этого:
unsigned int x = 0xFFFFFFFF;
int y = 0xFFFFFFFF;
if (x < 0)
printf("one\n");
else
printf("two\n");
if (y < 0)
printf("three\n");
else
printf("four\n");
Ответ 2
Да, потому что в вашем случае они используют то же представление.
Бит-шаблон 0xFFFFFFFF
выглядит как -1, когда интерпретируется как целое число со знаком 32b и как 4294967295, когда интерпретируется как целое число без знака 32b.
Это то же самое, что и char c = 65
. Если вы интерпретируете его как целое число со знаком, то оно 65. Если вы интерпретируете его как символ, то a
.
Как показывают R и pmg, технически это поведение undefined для передачи аргументов, которые не соответствуют спецификаторам формата. Таким образом, программа может делать что угодно (от печати случайных значений до сбоев, печати "правильной" вещи и т.д.).
Стандарт указывает на 7.19.6.1-9
Если спецификация преобразования недействительна, поведение не определено. Если любой аргумент не является правильным типом для соответствующего преобразования спецификация, поведение не определено.
Ответ 3
Нет никакой разницы между ними в том, как они хранятся в памяти и регистры, нет никакой подписанной и неподписанной версии int-регистров, нет никакой подписанной информации, хранящейся в int, разница становится актуальной только при выполнении математических операций, есть подписанная и неподписанная версия математических операций, встроенных в ЦП, и подписанность сообщает компилятору, какую версию использовать.
Ответ 4
Проблема заключается в том, что вы вызывали Undefined поведение.
Когда вы вызываете UB, все может случиться.
Назначения в порядке; существует неявное преобразование в первой строке
int x = 0xFFFFFFFF;
unsigned int y = 0xFFFFFFFF;
Однако вызов printf
не работает
printf("%d, %d, %u, %u", x, y, x, y);
UB не соответствует спецификатору %
и типу аргумента.
В вашем случае вы укажете 2 int
и 2 unsigned int
в этом порядке, предоставив 1 int
, 1 unsigned int
, 1 int
и 1 unsigned int
.
Не выполняйте UB!
Ответ 5
Внутреннее представление int
и unsigned int
одинаков.
Поэтому, когда вы передаете одну строку формата в printf
, она будет напечатана как одна и та же.
Однако при сравнении они отличаются.
Рассмотрим:
int x = 0x7FFFFFFF;
int y = 0xFFFFFFFF;
x < y // false
x > y // true
(unsigned int) x < (unsigned int y) // true
(unsigned int) x > (unsigned int y) // false
Это также может быть оговоркой, потому что при сравнении целого числа, подписанного и без знака, одно из них будет неявно выбрано для соответствия типам.
Ответ 6
тип просто сообщает вам, что должен представлять битовый шаблон. биты - это только то, что вы их делаете. одни и те же последовательности можно интерпретировать по-разному.
Ответ 7
Функция printf
интерпретирует значение, которое вы передаете в соответствии с спецификатором формата в соответствующей позиции. Если вы сообщите printf
, что вы передаете int
, но передаете unsigned
вместо этого, printf
будет переинтерпретировать один как другой и распечатать результаты, которые вы видите.
Ответ 8
Он спрашивает о реальной разнице.
Когда вы говорите о поведении undefined, вы находитесь на уровне гарантии, предоставляемой спецификацией языка, - это далеко не реальность.
Чтобы понять реальную разницу, проверьте этот фрагмент (конечно, это UB, но он отлично определен в вашем любимом компиляторе):
#include <stdio.h>
int main()
{
int i1 = ~0;
int i2 = i1 >> 1;
unsigned u1 = ~0;
unsigned u2 = u1 >> 1;
printf("int : %X -> %X\n", i1, i2);
printf("unsigned int: %X -> %X\n", u1, u2);
}
Ответ 9
Это довольно прямолинейно. Бинарное представление - это ключ, о котором он упоминается, но никогда не отображается.
Без знака в HEX, если 0XFFFFFFF = машинный код = 1111 1111 1111 1111 1111 1111 1111 1111 = 4 294 967 295 положительные представления числа.
Это все прекрасно и денди, но нам нужен способ представления отрицательных чисел.
Таким образом, мозги решили добавить два дополнения.
Что это значит хорошо, короче говоря, они взяли левую самую цифру и решили, что, когда она равна 1 (за ней следуют все до тех пор, пока вы не достигнете самого значимого бита), число будет отрицательным, если оно положительно.
Теперь посмотрим, что произойдет 0000 0000 0000 0000 0000 0000 0000 0011 = 3.
Теперь давайте продолжим добавлять к этому числу
0111 1111 1111 1111 1111 1111 1111 1111 = 2,147,483,645
наивысшее положительное число с подписанным int.
Пусть добавьте 1 (здесь вы можете посмотреть бинарное дополнение)
мы должны довести этот путь до конца.
1111 1111 1111 1111 1111 1111 1111 1110 = -1
Поэтому я предполагаю, что вкратце можно сказать, что разница в том, что одна из них допускает отрицательные числа, а другая - не из-за знака знака или оставила самый бит или самый старший бит.