Преобразование беззнакового символа в подписанный int

Рассмотрим следующую программу

void main(){
  char t = 179;
  printf("%d ",t);
}

Выход -77. Но двоичное представление 179

10110011

Таким образом, не должно быть -51, учитывая, что 1-й бит - это бит. Двоичное представление -77 есть

11001101

Кажется, что битовый порядок обратный. В чем дело? Пожалуйста, кто-нибудь посоветует.


person Gaurav Singh    schedule 15.04.2015    source источник
comment
en.wikipedia.org/wiki/Two%27s_complement   -  person ouah    schedule 15.04.2015
comment
Чтобы расширить приведенный выше комментарий, схема кодирования отрицательных чисел в двоичном формате, который вы ожидаете, называется знаком и величина, которая просто использует самый старший бит как знаковый бит. На практике это практически никогда не используется. Отрицательные числа обычно реализуются с помощью представления с двумя дополнениями.   -  person eigenchris    schedule 15.04.2015
comment
@eigenchris нет, это не величина знака, а дополнение до 2. Сегодня вы вряд ли сможете найти систему с дополнением до единицы или знак-величина. Оба -77 и 179 представляют собой 0xB3   -  person phuclv    schedule 15.04.2015
comment
@ LưuVĩnhPhúc, возможно, я плохо сформулировал свой комментарий ... Я хочу сказать, что OP ожидал, что знак и величина - это то, что они предполагали, что 10110011 является представлением -51. Конечно, на самом деле 10110011 равно -77 в представлении дополнения до двух, которое сегодня является стандартным представлением отрицательных чисел.   -  person eigenchris    schedule 15.04.2015


Ответы (5)


Вы утверждали, что двоичное представление -77 - это 11001101, но разворот принадлежит вам. Двоичное представление -77 - 10110011.

Двоичный 10110011 без знака является десятичным 179.

Двоичный 10110011 со знаком является десятичным -77.

Вы присвоили значение 179 вне допустимого диапазона для signed char. Теоретически это могло быть Undefined Behavior, но, помимо выдачи ошибки, это был бы очень плохой компилятор, который помещал что-либо, кроме этого 8-битного значения в signed char.

Но при печати оно интерпретируется как отрицательное число, потому что установлено b7.

person Weather Vane    schedule 15.04.2015

Похоже, что char - это подписанный тип в вашей системе. Допустимый диапазон для char будет [-128, 127]

Используя

char t = 179;

компилятор использует дополнение 2 до 179 (что, скорее всего, составляет -77) и присваивает это значение t.

person R Sahu    schedule 15.04.2015
comment
Это неопределенное поведение. - person Maxim Egorushkin; 15.04.2015
comment
@MaximEgorushkin это не так, смотрите правила преобразования целых чисел. - person ouah; 15.04.2015
comment
@ouah Присваивает символу значение больше, чем CHAR_MAX. Это неопределенное поведение. - person Maxim Egorushkin; 15.04.2015
comment
@ouah Процитируйте правило, на которое вы ссылаетесь. - person Maxim Egorushkin; 15.04.2015
comment
@MaximEgorushkin c11, 6.3.1.3p3 - person ouah; 15.04.2015
comment
@ouch Спасибо за указатель. Эти правила говорят: Когда значение с целочисленным типом преобразуется в другой целочисленный тип, отличный от _Bool, если значение может быть представлено новым типом, оно не изменяется. В противном случае, если новый тип является беззнаковым, значение преобразуется путем многократного добавления или вычитания на одно целое число без знака больше, чем максимальное значение, которое может быть представлено в новом типе, до тех пор, пока значение не окажется в диапазоне нового преобразования в тип. В противном случае новый тип подписан и значение не может быть представлено в нем. - person Maxim Egorushkin; 15.04.2015
comment
@MaximEgorushkin Я не понимаю, как значение преобразуется путем многократного добавления или вычитания на одно целое число без знака больше, чем максимальное значение, которое может быть представлено в новом типе, пока значение не окажется в диапазоне нового преобразования в тип < / я>. переводится в 2-кратное дополнение к присвоенному номеру. Но это тема для другого вопроса. - person R Sahu; 15.04.2015
comment
@RSahu Это усечение битов более высокого порядка, которое хорошо определено для беззнаковых типов, но не для подписанных. - person Maxim Egorushkin; 15.04.2015
comment
@MaximEgorushkin Я думаю, вы неправильно процитировали абзац: В противном случае новый тип подписан и значение не может быть представлено в нем; либо результат определяется реализацией, либо возникает сигнал, определяемый реализацией. Важной частью является результат определяется реализацией или возникает сигнал, определенный реализацией. - person ouah; 15.04.2015
comment
@ouah Достаточно честно, я часто путаю определенный реализацией с undefined. - person Maxim Egorushkin; 15.04.2015

Чтобы преобразовать положительное и отрицательное число в 2 дополнения, вы инвертируете все биты, а затем добавляете 1.

10110011

01001100 (инвертировать все биты)

01001101 (добавить)

Это 77 десятичных знаков

person Brad Budlong    schedule 15.04.2015

Char может быть подписанным или беззнаковым: это зависит от вашего компилятора.

Если подписано, это может быть 2 или 1 дополнение.

Кроме того, он может быть больше 8 бит, хотя sizeof char определен равным 1.

Поэтому полагаться на конкретное представление нецелесообразно.

person Bathsheba    schedule 15.04.2015
comment
Публикуем совместно. C ++ будет настаивать на дополнении 2s в следующем стандарте: не знаю о C - person Bathsheba; 15.04.2015

Обратите внимание, что во многих системах char подписан. Следовательно, когда вы назначаете 179 (который имеет тип int) для char, это значение выходит за пределы диапазона char, следовательно, это неуказанное поведение.

6.3.1.3 Целые числа со знаком и без знака:

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

Если вы измените тип на unsigned char, ваша программа будет работать правильно.

Также обратите внимание, что char, signed char и unsigned char - это 3 разных типа, в отличие от int и signed int. Подпись char определяется реализацией.

person Maxim Egorushkin    schedule 15.04.2015
comment
Сначала вы сказали, что это неопределенное поведение, а теперь вы говорите, что это неопределенное поведение, и ни то, ни другое не является правильным, поскольку C имеет конкретные определения для этих формулировок. Правильнее сказать: результат определяется реализацией или возникает сигнал, определенный реализацией. - person ouah; 15.04.2015