2012-05-06 2 views
4

Я читал книгу Сокеты TCP/IP в Java, 2nd Edition. Я надеялся получить больше ясности в чем-то, но, поскольку на веб-сайте книги нет форума или чего-то еще, я думал, что попрошу здесь. В нескольких местах книга использует маску байта, чтобы избежать расширения знака. Вот пример:Предотвращение расширения знака с помощью байтной маски

private final static int BYTEMASK = 0xFF; //8 bits 

public static long decodeIntBigEndian(byte[] val, int offset, int size) { 
    long rtn = 0; 
    for(int i = 0; i < size; i++) { 
     rtn = (rtn << Byte.SIZE) | ((long) val[offset + i] & BYTEMASK); 
    } 
    return rtn; 
} 

Итак, вот моя догадка о том, что происходит. Дай мне знать, если я прав. BYTEMASK в двоичном виде должно выглядеть как 00000000 00000000 00000000 11111111. Чтобы упростить задачу, давайте просто скажем, что байт-байт val содержит только 1 короткий, поэтому смещение равно 0. Поэтому давайте установим массив байтов в val[0] = 11111111, val[1] = 00001111. На i = 0, rtn все 0, поэтому rtn << Byte.SIZE просто сохраняет значение одинаково. Тогда есть (long)val[0], что делает его 8 байтами со всеми 1 из-за расширения знака. Но когда вы используете & BYTEMASK, он устанавливает все лишние 1 в 0, оставляя последний байт всех 1. Затем вы получаете rtn | val[0], который в основном переворачивает все 1 в последнем байте rtn. Для i = 1, (rtn << Byte.SIZE) выталкивает младший байт и оставляет все 0 на месте. Затем (long)val[1] делает длинный со всеми нулями плюс 00001111 для наименее значимого байта, который мы хотим. Поэтому использование & BYTEMASK не меняет его. Затем, когда используется rtn | val[1], он переворачивает младший байт rtn на все 1. Конечное значение возврата теперь составляет rtn = 00000000 00000000 00000000 00000000 00000000 00000000 11111111 11111111. Итак, я надеюсь, что это было не слишком долго, и это было понятно. Я просто хочу знать, правильно ли я думаю об этом, а не просто полностью нарушил логику. Кроме того, меня смущает одна вещь: BYTEMASK - 0xFF. В двоичном коде это будет 11111111 11111111, поэтому, если он неявно передается в int, не будет ли это на самом деле 11111111 11111111 11111111 11111111 из-за расширения знака? Если это так, то для меня не имеет смысла, как бы работать BYTEMASK. Спасибо за чтение.

+2

'0xFF' - это int, почему он должен быть расширен? А в двоичном виде это будет '11111111'. –

+0

С первого взгляда этот пост выглядит странно похожим на позорный пост «XHTML с регулярным выражением» ... – Tharwen

+1

Пони он приходит. –

ответ

7

Все права на последний момент, за исключением:

0xFF это уже int (0x000000FF), поэтому он не будет по знаку. В общем, integer number literals на Java - это int с, если они не заканчиваются L или l, а затем они являются long.

+0

Благодарим вас за ответ. +1 к вам, если у меня хватило репутации, чтобы сделать это. – elveatles

+0

@elveatles * Примите * ответ. Это то, что вам следует делать в любом случае, и вы также получите некоторую репутацию за это. Нажмите галочку слева от ответа. –