Реальная разница между "int" и " unsigned int"

int:

32-битный тип данных int может содержать целочисленные значения в диапазоне -2,147,483,648 до 2,147,483,647. Вы также можете ссылаться на этот тип данных как signed int и signed.

unsigned int :

32-разрядные данные int без знака типа могут содержать целочисленные значения в диапазоне от 0 до 4,294,967,295. Вы может также ссылаться на этот тип данных просто как unsigned.

Ok, но, в практика:

int x = 0xFFFFFFFF;
unsigned int y = 0xFFFFFFFF;
printf("%d, %d, %u, %u", x, y, x, y);
// -1, -1, 4294967295, 4294967295

никакой разницы, О. О. Я немного запутался.

9 ответов


хехе. У вас есть неявный бросок здесь, потому что вы говорите 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");

Да, потому что в вашем случае они использовать такое же представление.

битовый шаблон 0xFFFFFFFF выглядит как -1 при интерпретации как целое число со знаком 32b и как 4294967295 при интерпретации как целое число без знака 32b.

это то же самое как char c = 65. Если вы интерпретируете его как целое число со знаком, это 65. Если вы интерпретируете его как символ, это a.


как указывают R и pmg, технически это неопределенное поведение для передачи аргументы, не соответствующие спецификаторам формата. Таким образом, программа могла делать все (от печати случайных значений до сбоя, до печати "правильной" вещи и т. д.).

стандарт указывает на это в 7.19.6.1-9

если спецификация преобразования является недопустимым, поведение неопределено. если любой аргумент не является правильным типом для соответствующего преобразования спецификация, поведение не определено.


нет никакой разницы между ними в том, как они хранятся в памяти и регистрах, нет подписанной и неподписанной версии регистров int нет подписанной информации, хранящейся в int, разница становится актуальной только при выполнении математических операций, есть подписанная и неподписанная версия математических операций, встроенных в процессор, и signedness сообщает компилятору, какую версию использовать.


проблема в том, что вы вызвали Неопределено Поведение.


при вызове УБ все может случиться.

назначения в порядке; есть неявное преобразование в первой строке

int x = 0xFFFFFFFF;
unsigned int y = 0xFFFFFFFF;
вызов printf, это не ок
printf("%d, %d, %u, %u", x, y, x, y);

это УБ несоответствия % спецификатор и тип аргумента.
В вашем случае вы указываете 2 ints и 2 unsigned ints в этом порядке, предоставив 1 int, 1 unsigned int, 1 int и 1 unsigned int.


не УБ!


внутреннее представление 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

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


Он спрашивает о реальные разницы. Когда вы говорите о неопределенном поведении вы находитесь на уровне гарантии, предоставленной спецификации языка - это далеко от реальности. Чтобы понять реальную разницу, пожалуйста, проверьте этот фрагмент (конечно, это 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);
}

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


на printf функции интерпретирует значение, которое вы передаете в соответствии со спецификатором формата в соответствующей позиции. Если ты скажешь printf Что вы передаете int и unsigned вместо printf повторно интерпретировать один в другой, и печатать результаты, которые вы видите.


Это довольно прямо вперед. Двоичное представление-это ключ, который упоминается, но никогда не отображается. Unsigned в HEX, если 0XFFFFFFF = машинный код = 1111 1111 1111 1111 1111 1111 1111 1111 = 4,294,967,295 положительные представления числа. Это все хорошо и денди, но нам нужен способ представления отрицательных чисел. Так что мозги решили дополнить двоек. Что это значит хорошо, короче говоря, они взяли самую левую цифру и решили, что когда это 1 (затем все, пока вы не достигнете левого наиболее значимого бита) число будет отрицательным, если оно равно 0, оно положительное. Теперь давайте посмотрим, что происходит 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 Поэтому я думаю, короче говоря, мы могли бы сказать, что разница заключается в том, что один допускает отрицательные числа, а другой нет, что связано с знаковый бит или левый бит или бит.