0xff << n은 Java에서 무엇을합니까?
Inputstream에서 처음 4 바이트를 읽고이 경우 Stream의 크기 / 렌즈에 대한 정보를 얻기 위해 압축했습니다.
이를 위해 다른 프로젝트에서 복사 한 다음 코드 (예제 1)를 사용합니다.
예 1 : 바이트 배열을 사용합니다. 여기서 값은 길이가 4이고 값이 {0,0,12,26} 인 in_buf [] 라는 배열로 InputStream에서 읽 힙니다.
예 1
int size = (((in_buf[0] & 0xff) << 24) | ((in_buf[1] & 0xff) << 16) |
((in_buf[2] & 0xff) << 8) | (in_buf[3] & 0xff)); // result its 3098
결과적으로 나는 크기의 가치가 되지만 ..
나는 여기서 무슨 일이 일어나는지 설명해야하고, 무슨 일이 일어나는지 더 잘보고 디버그하기 위해 모든 기능을 분할하려고 시도하고 결과를 따르게됩니다
int byte1 = ((in_buf[0] & 0xff) << 24); // result 0
int byte2 = ((in_buf[1] & 0xff) << 16); // result 0
int byte3 = ((in_buf[2] & 0xff) << 8); // result 3072
int byte4 = (in_buf[3] & 0xff); // result 26
그런 다음 예제 1에서 크기 의 결과가 0 + 0 + 3072 + 26의 합이 아니라고 추론합니다. 그러나 여기서 정확히 어떤 일이 발생합니까 (값 12와 26에서만)? 또는 어떤 작업을 수행합니까?
이 같은 ?
0000 0000 0000 1100 //12 << 8
0000 1100 0000 0000 // result after << 8
그리고 왜 우리는 마스크 & 0xff를 사용해야 합니까?
int byte3a = (in_buf [3] & 0xff) 디버그 할 때 결과는 int byte3b = in_buf [3]와 동일하지 않습니다. 그래서 12 , * 여기서 in_buf [3] = 12의 값; 디버그 결과에서 이미지를 추가합니다.
무슨 일이 일어나거나 이것을 in_buf [3] & 0xff 와 같이 만드 나요?
0000 0000 0000 1100 (12)
& 0000 0000 1111 1111 (0xff)
-------------------
0000 0000 1111 0011 ?
Eclipse의 스크린 샷
답변
이런거?
예, 피연산자가 숫자 승격을 거쳐 으로 바뀌는 것을 제외하고 int는 기술적으로 32 비트를 표시해야합니다.
왜 마스크를 사용해야
& 0xff합니까?
우리가 긍정적으로 부정적인 바이트를 처리하므로입니다 ints본질적으로 무엇을 toUnsignedInt하고있다. 음수가 아닌 바이트에 대해서는 아무것도 수행하지 않지만 음의 바이트에 대해서는 다음과 같이 말하십시오 -1.
1111 1111
int숫자 승격으로 인해로 변환되면 32 비트로 부호 확장 됩니다. 즉, 부호가 음수로 유지됩니다. 기본적으로 이것은 숫자가 음수이면 1을 채우고 그렇지 않으면 0을 채 웁니다. 따라서 다음과 같이 -1됩니다.
1111 1111 1111 1111 1111 1111 1111 1111
이제를 사용하면 << 8다음과 같습니다.
1111 1111 1111 1111 1111 1111 0000 0000
입니다 -256. 이제 & 0xff이전에 했을 경우 어떻게되는지 봅시다 << 8. 숫자 승격이 발생하고 이전과 마찬가지로 바이트를 32 개로 변환하지만 & 0xff최하위 8 비트 만 가져옵니다! 따라서 int는 이제 다음과 같습니다.
0000 0000 0000 0000 0000 0000 1111 1111
이것은 0으로 패딩하여 원래 바이트를 얻는 방법입니다. 그리고 << 8명백한 일을합니다 :
0000 0000 0000 0000 1111 1111 0000 0000
example1에 표시된 코드는 배열의 처음 4 개 값 ( "입력 스트림"또는 해당 값으로 설명하는 내용을 포함 할 수 있음)을 사용합니다. 그것들을 단일 변수, 아마도 충분한 너비의 (부호없는) 정수로 배열합니다.
지정하지 않은 프로토콜에 따라 처음 4 개 값의 의미 론적 의미를 가져 오기 위해 그렇게합니다.
그렇다면 왜 그 연산자를 사용하여 "회전"방식으로 그렇게할까요?
를 사용 & 0xff하면 하위 8 비트 만 사용됩니다.
이것은 불필요합니다. 즉, 바이트에서 나오는 배열의 값에 의존 할 수 있고 따라서 최대 비트 7까지의 값만 포함 할 수있는 경우에 필요하지 않습니다. 더 높은 비트 (값 256, 512, ...)가없는 경우 고려됩니다. 이것은 스트림에서 배열로의 단일 바이트 검색을 신뢰하지 않는 경우에 의미가 있습니다.
그러나 자바에서는 (해롤드가 주석에서 친절하게 지적했듯이)
& 0xffbyte는 서명 된 유형이므로 int로 변환 될 때 부호 확장되고 부호의 추가 사본을 제거해야하기 때문에 Java에서 중복되지 않습니다. 바이트가 서명되지 않은 경우 이와 같은 많은 코드를 절약 할 수 있습니다.
사용 << N하여, N8의 배수 인, 그들은 결과 값의 정확한 영향을 결과 값으로 내부 위치에 팔 "채취"비트를 이동시킨다. 바이트 중 하나 (여기서는 의도적으로 "first"를 사용하지 않음)는 가장 낮은 값 위치에 속하며 이동되지 않으며 해당 값은 그대로 사용됩니다. 다음으로 높은 값의 바이트로 1 바이트가 필요합니다. 즉, 256의 배수 (0x100)를 나타냅니다. 등등.
의 사용은 |올바르게 배치 된 부품 을 조립합니다.
이제 왜 이렇게 복잡한 방식으로 수행합니까? 명백한 대안은 비트 7을 넘어서는 모든 비트를 죽이고 그 로트를 하나의 4 바이트 정수로 읽는 것입니다.
그 이유는 엔디 아니스에 대한 의심입니다. 메모리에서 특정 순서로 4 바이트를 배열하는 것이 하나의 4 바이트 값으로 읽 히면 환경에서 목표로하는 값으로 해석 될 것이라고 믿지 못할 수도 있습니다. 이는 가장 낮은 주소의 바이트가 가장 낮은 값을 나타내는 바이트인지 가장 높은 값을 나타내는 것으로 간주되어야하는지 여부에 따라 환경에 따라 의견이 다를 수 있기 때문입니다.
표시된 코드는 선택한 바이트를 높은 값으로, 하나는 낮은 값으로, 다른 하나는 그 사이에 강제합니다.
값을 8 비트 바이트로 강제합니다.
자바는 더 부호없는 유형의 바이트 값이 없기 때문에 0xFF로 해석됩니다 -1자바의 특성으로 인해 그것을 즉 32 비트 INT, 승진 될 것이다 0xFFFFFFFF.
비트 마스크는 OR 비트 연산자를 사용할 때 비트를 덮어 쓰지 않도록 음수 값에 대한 추가 비트를 버리는 것을 의미합니다 |.
다음은 바이트 값이 255로 해석 -1되고 승격되는 예입니다.int
1111 1111 1111 1111 1111 1111 1111 (-1, but was originally an unsigned byte of 255)
& 0000 0000 0000 0000 0000 1111 1111 (0xff)
----------------------------------
0000 0000 0000 0000 0000 1111 1111 (an int with the original value of 255)
이진 연산입니다.
정확히 어떻게 되나요?
& 0xFF기본적 수단, 당신은 마지막 바이트를 취할.
바이너리 및 (&)는 1이 같은 위치에있는 두 숫자에 모두있는 경우에만 결과 위치에서 1이됩니다 (그렇지 않으면 0).
또 다른 예가 있습니다.
0000 0001 0000 1100 (268)
& 0000 0000 1111 1111 (0xff)
-------------------
0000 0000 0000 1100 (12)
12는 어떻게 되나요?
0000 0000 0000 1100 (12)
& 0000 0000 1111 1111 (0xff)
-------------------
0000 0000 0000 1100 (12)
시프트:
왼쪽 시프트는 비트를 왼쪽으로 밀어냅니다.
0000 0000 0000 1100 (12)
<< 8
-------------------
0000 1100 0000 0000 (3072)
26은 어떻게 되나요?
0000 0000 0001 1010 (26)
& 0000 0000 1111 1111 (0xff)
-------------------
0000 0000 0001 1010 (26)
왜 마스크와 0xff를 사용해야합니까?
이 경우에는 그렇지 않습니다. 하지만 더 큰 숫자 (또는 음수)로 작업했다면 마스크를 사용해야 할 수도 있습니다. 또한 추가로 지저분한 부분이 없는지 확인하십시오.
또는 다음과 같이 모두 통합 :
예, 기본적으로 추가이지만이 경우에만 해당됩니다. 실제로 일어나는 일은 당신이 만든 바이트 & 0xFF를 서로 옆에 두어 숫자를 만드는 것입니다. 그것이 당신이 8의 곱셈으로 이동하는 이유입니다-모든 바이트는 크기 8의 위치를 가지고 있습니다.
X, Y, Z, W 바이트가 있다고 가정 해 보겠습니다. 그런 다음 다음 (X<<24)|(Y<<16)|(Z<<8)|W과 같이 이진수로 구성된 숫자를 만듭니다 XYZW.. 이 숫자의 합계 일 필요는 없습니다.