2012-05-03 2 views
2

Учитывая, что байты, короткие и int подписаны, почему байт и короткие на Java не получают обычную обработку signed two's complement? Например, 0xff является незаконным для байта.Байт не подписан двумя дополнениями?

Это обсуждалось до here, но я не мог найти причину, почему это так.

ответ

4

Если вы посмотрите на фактическую память, используемую для хранения -1 в подписанном байте, вы увидите, что это 0xff. Однако в самом языке, а не в двоичном представлении, 0xff просто выходит за пределы для байта. Бинарное представление -1 действительно будет использовать два дополнения, но вы защищены от этой детали реализации.

Дизайнеры языка просто взяли позицию, что попытка сохранить 255 в типе данных, который может содержать только -128 до 127, следует считать ошибкой.

Вы спросите в комментариях, почему Java позволяет:

int i = 0xffffffff; 

Буквальный 0xffffffff является int буквальным и интерпретируется с помощью дополнения до двух. Причина, по которой вы не можете сделать ничего подобного для байта, заключается в том, что язык не дает синтаксиса для указания того, что литерал имеет тип byte или действительно short.

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

+0

Спасибо за понимание, что реализация является дополнением двух. Почему же тогда язык допускает 0xffff_ffff для int? – Sridhar

1

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

0

Возможные значения для byte диапазоне от -128 до 127.

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

Тогда мы имеем:

byte b = 128; 
if (b < 0) { 
    // yes, the value magically changed from 128 to -128... 
} 

В большинстве случаев это лучше иметь компилятор скажет вам, что значение находится вне диапазона, чем «исправить» это так.

4

Вы можете написать

int i = 0xFFFFFFFF; 

, но вы не можете писать

byte b = 0xFF; 

как 0xFF является int значение не byte поэтому его равным 255. Там нет способа, чтобы определить байтом или коротким литералом, поэтому вам нужно отдать его.

BTW Вы можете сделать

byte b = 0; 
b += 0xFF; 
b ^= 0xFF; 

даже

byte b = 30; 
b *= 1.75; // b = 52. 
+0

Спасибо. Недавно я узнал о неявном метании в + =. В Java я согласен 0xff является int. Что есть, то есть. Но обычно 0xff подписывается 8 бит, поэтому его следует присваивать байту. Во всяком случае, я думаю, на вопрос ответил - байт реализован как дополнение к двум. – Sridhar

+0

Отсутствует отсутствие типа байтового литерала, поэтому 0xFF может быть только на 255. Нет никакого способа написать 0xFF, который является байтом без приведения. c.f. '0xFFL' является' long' –

+0

Вы верны. Однако вы можете написать это. И.Е. байт b = (байт) 0xFF; Конечно, он терпит неудачу как -1, хотя :-) –

1

Вы можете буквально установить байт, но удивительно, что вы должны использовать большее количество цифр:

byte bad = 0xff; // doesn't work 
byte b = 0xffffffff; // fine 

Логика является , что 0xff неявно 0x000000ff, что превышает диапазон байта. (255)

Это не первая идея, которую вы получаете, но она имеет некоторую логику. Более длинное число - меньшее (и меньшее абсолютное значение).

byte b = 0xffffffff; // -1 
byte c = 0xffffff81; // -127 
byte c = 0xffffff80; // -128 
Смежные вопросы