C/C++ bit shift 연산

Monaca: [퀴즈] 비트 이동 연산의 결과는 어떻게 될까? 에서 트랙백.

bit 를 직접 다루는 몇 몇 연산자(명령어?)들의 경우엔 꽤나 의외의 결과를 낳는 경우가 있다. (특히 컴퓨터 구조에 대한 관심이 적을 경우 더욱 그렇다)
물론 기본적인 키워드도 이해 못해서 삽질하는 경우도 많은 세상이니 알아두면 알아둘수록 “의외다” 라고 말하는 경우는 줄어든다. 여튼 본론으로 넘어가자.

monaca 님이 낸 문제의 답은 32bit Fedora / GCC 에서 다음과 같은 답이 나온다.

32
16
32

이건 intel asm 에서 저 명령어가 31(하위 5bit이 1인 값)과 and 연산된 shift 길이를 쓰기 때문에 그랬던 것이고. (.net framework의 경우엔 언어 명세에서 저런 동작을 보인다고 명시한다)

추가로,

object 님이 저 글에 쓴 댓글이,

<< 보다는 >> 가 더 재밌지 않나요? << 은 항상 LSB를 0으로 채우지만.. logical right shift하고 arithmetic right shift 같은 차이 점은.. 제법 당황할 애들도 좀 많을 듯.

이게 좀 재밌음(…).

그런 의미에서 간단한 문제.

int a = 2147483647; // 2^31 – 1

unsigned int ua = 2147483647;

printf(“%d\n”, (a << 1) >> 1 );

printf(“%d\n”, (ua << 1) >> 1 );

32bit 플랫폼에서 실행한 경우 위의 코드는 어떤 결과가 나오는가?[1]

hint: signed/unsigned 와  arithmetic/logical shift 의 관계를 알면 풀 수 있다. Java 같은 언어에선 완전히 다른 얘기가 되긴하지만[…]

ps. 하지만 이쯤에서 엽기적인 결과도 하나 보여줘야지. 다음은 32bit python 에서 장난 친 것

>>> a = 16
>>> a << 1
32
>>> a << 33
137438953472L
>>> a << 65
590295810358705651712L
>>>

built-in integer가 꽤나 높은 정밀도를 가지고 있는 python의 위력(?)

  1. 64bit도 int가 4bytes인 경우가 왕왕 있긴하지만, SUN OS(solaris) 같은 애들은 안 그러니 일단 32bit CPU(적어도 실행 모드가), 32bit OS/compiler를 가정함 []

Published by

rein

나는 ...

15 thoughts on “C/C++ bit shift 연산”

  1. 저 코드 붙여넣으니 ”때문에 그냥 안 붙는군. 자바는 >>, >>>가 있으니. 이진 검색에서 int mid = (low + high) / 2;의 오버플로 버그를 int mid = (low + high) >>> 1;로 해결한 게 인상적이었음.

  2. java 언어에서의 >> 와 >>> 의 차이점에 대해서 공부하던 것이 기억나는 문제로군요. 처음 배울 때 저거 가지고 좀 낚였죠 :D

  3. 사실 컴퓨터를 모르는 일반인이 보기에는 파이썬 결과가 훨씬 더 정상적일 듯 한데 :)

    파이썬3000 부터는 심지어 L도 안 붙음.

  4. int에 대해 >>, <<를 할 때는 하위 5비트와 and 연산을 한 값이 이용되고 short, byte일 때는 각각 4비트, 3비트 만큼이 되고요.. 64비트일땐 또 6비트만큼 짤라서 써요. 재밌는 건 디버거에서 한번 직접 저거 해보세요. 그러면 항상 0이 나와요 ㅋㅋ

  5. 근데 솔직히 모나코님 문제가 그렇게 생각할 거리인 줄은 모르겠음. 폭보나 큰 쉬프트 연산이 저렇게 되는 건 그냥 기계 디자인 때문인 듯 한데.

    차라리 여기 있는 문제가 좀 더 의미 있어 보임. 컴퓨터 상에서 음수를 어떻게 표현하는지, 그리고 unsinged와 signed의 오른쪽 쉬프트가 어떻게 다른지 등등의 지식을 알고 있는지 물어 보는 거니까.

  6. 답글이 수정이 안되어서 지저분하게 주렁주렁 달아요 :)

    64비트 int의 경우에는 3F와 &를 하는 것은 맞네요. 즉 0~63까지가 의미있는 값이 되고, 나머지들은 전부 1F와 &한 뒤에 한다고 IA-32 메뉴얼에 나와있네요.

    (참고로 x86-64에서는 int는 무조건 4바이트에요. SUN에서는 int가 기본으로 8바이트인가요?)

  7. 일념 / 그 문제 Programming Pearls(생각하는 프로그래밍)에 나온 binary search의 숨겨진 버그였죠 아마(…)

    고어핀드 / Java는 언어 명세 자체가 저런 고민은 적게하게 된듯도

    수원 / 음 그래도 저 자체는 나름 재미있는 문제이긴한듯도요.
    추상화에 의지하는 건 좋지만, 내부를 들여다보는것도 재밌고 의미있는듯하거든요

    object / 음; 64bit는 그렇겠네요. SUN ultrasparc 2에서 테스트했을 때는 GCC 64bit / 64bit solaris 8 환경에서는 int, long, pointer-type 모두 8바이트였습니다. IA-32 매뉴얼도 하나 있어야할텐데 요즘도 그냥 공짜로 보내주던가요;;

  8. CPU Instruction에 대해서 모르는 사람들 한테는 좀 엄하겠지만,
    C/C++은 어셈블리랑 같은 결과를 내 주기때문에 저는 이쪽이 더 편하더군요 [..]
    ps. IA-32/64메뉴얼은 인텔 사이트에서 PDF로 받아볼 수 있습니다.
    하드카피 된것도 보내주는지는 모르겠네요.

    1. C/C++이 어셈블리 결과를 내 줘서 편하다고 할 수도 있지만, byte-code compile을 하는 대부분의 VM 기반 혹은 스크립트 언어들도 저 경우의 문제(?)는 적다고 생각합니다.

      IA-32/64 매뉴얼을 받을 수 있는 것은 알고 있습니다.
      근데 예전(…이래봐야 4년 전?)에는 요청하면 우편으로 하드카피를 줬던 걸로 기억해서(…)

Leave a Reply