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를 가정함. ↩︎