[c] 비트 시프트는 엔디안에 의존합니까?

내가 숫자를 'numb'=1025 [00000000 00000000 00000100 00000001]표현 했다고 가정 해보십시오 .

리틀 엔디 언 머신에서 :

00000001 00000100 00000000 00000000

빅 엔디안 머신에서 :

00000000 00000000 00000100 00000001

이제 10 비트에 왼쪽 시프트를 적용하면 (즉 : numb << = 10) 다음을 가져야합니다.

[A] Little-Endian 머신에서 :

GDB에서 알 수 있듯이 Little Endian은 왼쪽 이동을 3 단계로 수행합니다.

  1. 아니오를 취급하십시오. 빅 엔디안 컨벤션에서 :

    00000000        00000000        00000100    00000001
  2. 왼쪽-시프트 적용 :

    00000000        00010000        00000100        00000000
  3. Little-Endian에서 결과를 다시 나타냅니다.

    00000000        00000100        00010000        00000000 

[비]. 빅 엔디안 머신에서 :

00000000        00010000        00000100        00000000

내 질문은 :

리틀 엔디안 컨벤션에 직접 왼쪽 쉬프트를 적용하면 다음과 같이됩니다.

numb:

00000001 00000100 00000000 00000000

numb << 10:

00010000 00000000 00000000 00000000

그러나 실제로는 다음을 제공합니다.

00000000        00000100        00010000        00000000 

두 번째 결과 만 달성하기 위해 위의 세 가지 가상 단계를 보여주었습니다.

위의 두 결과가 다른 이유를 설명해주십시오. 실제 결과 numb << 10가 예상 결과와 다릅니다.



답변

엔디안은 값이 메모리에 저장되는 방식입니다. 엔디안과 상관없이 프로세서에로드 될 때 비트 시프트 명령은 프로세서 레지스터의 값에서 작동합니다. 따라서, 메모리에서 프로세서로의 로딩은 빅 엔디안으로 변환하는 것과 동일하며, 시프 팅 동작은 다음에오고 새로운 값은 메모리에 다시 저장되는데, 여기서 리틀 엔디안 바이트 순서가 다시 적용됩니다.

@jww 덕분에 업데이트 : PowerPC에서 벡터 이동 및 회전은 엔디안에 민감합니다. 벡터 레지스터에 값을 가질 수 있으며 시프트 는 little-endian 및 big-endian에서 다른 결과를 생성 합니다.


답변

C의 다른 부분과 마찬가지로 비트 시프트는 표현이 아닌 값으로 정의됩니다 . 1만큼 왼쪽 이동은 2로 곱셈되고 오른쪽 이동은 나눗셈입니다. (비트 단위 연산을 사용할 때와 마찬가지로 부호를주의하십시오. 모든 것이 부호없는 정수 유형에 대해 가장 잘 정의되어 있습니다.)


답변

어떤 시프트 명령이 더 높은 비트를 먼저 시프트하는지는 왼쪽 시프트로 간주됩니다. 어떤 시프트 명령이 하위 비트를 먼저 시프트 시키는가 올바른 시프트로 간주됩니다. 그런 의미에서의 동작 >><<에 대한 unsigned번호 엔디안에 의존하지 않습니다.


답변

컴퓨터는 우리가하는 방식대로 숫자를 쓰지 않습니다. 값은 단순히 이동합니다. 바이트 단위로 보겠다고 주장하면 (컴퓨터가 그렇게하는 방식은 아니지만) 리틀 엔디안 컴퓨터에서 첫 번째 바이트가 왼쪽으로 이동하고 초과 비트는 두 번째 바이트로 이동한다고 말할 수 있습니다. 등등.

(반드시, 리틀 엔디안은 더 높은 주소를 가진 수평이 아닌 수직으로 바이트를 쓰면 더 의미가 있습니다. 메모리 맵 다이어그램이 일반적으로 그려지는 방식입니다.)


답변

수용 된 대답은 엔디안이 메모리 관점의 개념이라고 지적합니다. 그러나 나는 그것이 그 질문에 직접 대답한다고 생각하지 않습니다.

일부 답변에 따르면 비트 단위 연산은 endianess에 의존하지 않으며 프로세서는 다른 방식으로 바이트를 나타낼 수 있습니다. 어쨌든, 그것은 엔디안이 추상화되는 것에 대해 이야기하고 있습니다.

그러나 예를 들어 종이에서 비트 단위로 계산할 때 엔디안을 먼저 언급 할 필요가 없습니까? 대부분의 경우 우리는 내재적으로 엔디안을 선택합니다.

예를 들어, 이와 같은 코드가 있다고 가정

0x1F & 0xEF

종이로 손으로 결과를 어떻게 계산할까요?

  MSB   0001 1111  LSB
        1110 1111
result: 0000 1111

여기에서는 빅 엔디안 형식을 사용하여 계산을 수행합니다. Little Endian을 사용하여 동일한 결과를 계산하고 얻을 수도 있습니다.

Btw, 코드로 숫자를 쓸 때 빅 엔디안 형식과 같다고 생각합니다. 123456또는 0x1F가장 중요한 숫자는 왼쪽에서 시작합니다.

다시, 종이에 이진 형식의 값을 쓰 자마자 우리는 이미 Endianess를 선택했으며 메모리에서 볼 때 가치를보고 있다고 생각합니다.

다시 질문으로 돌아 가면, 시프트 연산 <<LSB (최하위 바이트)에서 MSB (최고 바이트)이동하는 것으로 생각해야합니다 .

그런 다음 질문의 예는 다음과 같습니다.

numb=1025

리틀 엔디안

LSB 00000001 00000100 00000000 00000000 MSB

그래서 << 10될 수 10bit에서 LSB MSB로 이동.


<< 10Little Endian 형식의 단계별 비교 및 조작 :

MSB                                        LSB
    00000000  00000000  00000100  00000001  numb(1025)
    00000000  00010000  00000100  00000000  << 10

LSB                                        MSB
    00000000  00000100  00010000  00000000 numb(1025) << 10, and put in a Little Endian Format

LSB                                        MSB
    00000001  00000100  00000000  00000000 numb(1205) in Little Endian format
    00000010  00001000  00000000  00000000 << 1
    00000100  00010000  00000000  00000000 << 2
    00001000  00100000  00000000  00000000 << 3
    00010000  01000000  00000000  00000000 << 4
    00100000  10000000  00000000  00000000 << 5
    01000000  00000000  00000001  00000000 << 6
    10000000  00000000  00000010  00000000 << 7
    00000000  00000001  00000100  00000000 << 8
    00000000  00000010  00001000  00000000 << 9
    00000000  00000100  00010000  00000000 << 10 (check this final result!)

와! OP가 설명한대로 예상 결과를 얻습니다!

OP가 예상 한 결과를 얻지 못한 문제는 다음과 같습니다.

  1. 그가 LSB에서 MSB로 이동하지 않은 것 같습니다.

  2. 리틀 엔디안 형식으로 비트를 옮길 때 다음을 인식해야합니다.

LSB 10000000 00000000 MSB << 1있다
LSB 00000000 00000001 MSB, 없다
LSB 01000000 00000000 MSB

각 개인마다 8bits실제로 MSB 00000000 LSBBig Endian 형식으로 작성하기 때문 입니다.

그래서 그것은

LSB[ (MSB 10000000 LSB) (MSB 00000000 LSB) ]MSB


요약하면 :

  1. 비트 단위 연산은 blablablabla에서 추상화되었다고 말하지만, 비트 단위 연산을 직접 계산할 때 이진 형식을 종이에 적을 때 사용하는 엔디안을 여전히 알아야합니다. 또한 모든 연산자가 동일한 엔디안을 사용하도록해야합니다.

  2. OP는 기대 한 결과를 얻지 못했습니다.


답변