[C언어] 2의 보수 코딩
예전에 2의 보수에 대한 post를 작성 한 적이 있습니다. 문득 이 부분을 C언어로 코딩하면 재미있지 않을까 생각되어 한번 C언어로 코딩화 해보는 시간을 가져 봅니다.
1. 10진수를 2진수로 변환
C언어에서는 변수에 어떤 값을 넣더라도 그 값을 printf()문을 어떻게 출력 형식을 취하느냐에 따라서 그 결과를 다양하게 출력 할 수 있습니다. 정수를 "%0"로 취하면 8진수 형태로 출력 되고 "%x"로 취하면 16진수 형태로 출력이 됩니다. 참고로 2진수 형태는 printf()문의 출력형식은 없기 때문에 정수를 2진수 값으로 가정해서 자릿수 값을 출력해보는 코딩을 수작업으로 해보겠습니다.
예)
12 => 00001100
위와 같은 형태로 출력을 하게 만들려면 어떻게 해야 할까요. 12값을 2진수로 잘게 쪼개는 방법은 12을 계속 2로 나눈 몫을 나열하는 방법도 있지만 &연산을 이용하여 쉽게 쪼개는 방법을 취할까 합니다.
1100
&1000
--------
1000
이렇게 &연산자는 AND 연산자로 1과 1일 때 1이 나오고 1과 0일 때는 0이 나옵니다.
그래서 정수 12를 2진수로 출력 되게 하려면 다음과 같습니다.
1000 0000 => 0x80
의 값을 기준으로 12정수에 & 연산을 수행합니다. 총 8자리 비트를 비교해야 하기 때문에 루프문으로 8번 & 연산을 수행합니다. 참고로 각 자리비트를 비교해야 하기 때문에 쉬프트 연산을 별도로 0x80에 취해야 합니다.
1000 0000 => 0100 0000 => 0010 0000 ...
이런식으로 각 자리비트를 만들어서 & 연산을 수행해야 하는데 이 표현을 하려면 쉬프트 연산을 쉽게 표현이 됩니다.
b = 0x80;
b=b>>1;
이렇게 한칸씩 이동시키면 됩니다.
위 내용을 코딩화 하면,
int a=12;
int b=0x80;
int i;
int tmp[8];
for(i=0;i<8;i++){
if(a&b) tmp[i]=1;
else tmp[i]=0;
b=b>>1;
}
[결과]
이렇게 하면 12에 대한 각 자리비트의 1인지 0인지 확인을 통해 tmp[i]에 해당 자리 비트 값을 저장하게 됩니다.
2의 보수 변환
-12을 2의 보수를 취해 음수를 2진수 형태로 출력 해 볼까요.
예) 2의 보수 -12
12 =>
0000 1100
11110011
11110011+0000 0001 = 11110100
위 과정을 C언어로 코딩화 해야 합니다.
12를 2진화 해서 배열변수에 저장합니다.
for(i=0;i<8;i++){
if(a&b) tmp[i]=1;
else tmp[i]=0;
b=b>>1;
}
-12를 2의 보수를 취하기 위해서 1을 0으로 0을 1로 변환
for(i=0;i<8;i++){
printf("%d",tmp[i]);
if(tmp[i]==1) tmp[i]=0;
else tmp[i]=1;
}
마지막으로 +1을 더한다.
for(i=7;i>=0;i--){
if(tmp[i]==1) tmp[i]=0;
else {
tmp[i]=1;
break;
}
}
마지막 +1을 더하는 위 코딩을 자세히 보셔야 합니다. 약간 햇갈릴 수 있습니다. 역순으로 마지막 자리부터 1이면 +1을 하기 때문에 올림수로 계속 순차적으로 1일때는 해당 자리는 최종적으로 0이 되고 1이 올라가고 다음 비트자리가 1 or 0 이냐에 따라서 더하게 됩니다. 그런데 더하는 비트자리가 0이 되면 그 자리는 1이 되고 break 문으로 for문을 빠져 나오게 됩니다.
이렇게 해서 tmp[] 배열 변수에는 -12에 대한 2의 보수를 취한 2진수 값이 저장되게 됩니다.
3. 종합 코딩
이제는 정상적으로 위 과정이 동작하고 결과을 얻는지 확인 해야 겠지요.
[전체소스]
#include
int main(int argc, char *argv[]) {
int a=12;
int b = 0x80;
int i;
int tmp[8];
for(i=0;i<8;i++){
if(a&b) tmp[i]=1;
else tmp[i]=0;
b=b>>1;
}
printf("%d => \n",a);
for(i=0;i<8;i++){
printf("%d",tmp[i]);
}
printf("\n");
for(i=0;i<8;i++){
printf("%d",tmp[i]);
if(tmp[i]==1) tmp[i]=0;
else tmp[i]=1;
}
printf("\n");
for(i=0;i<8;i++){
printf("%d",tmp[i]);
}
printf("\n");
for(i=7;i>=0;i--){
if(tmp[i]==1) tmp[i]=0;
else {
tmp[i]=1;
break;
}
}
for(i=0;i<8;i++){
printf("%d",tmp[i]);
}
printf("\n");
return 0;
}
위 코딩을 보시면 -12에 대한 2의 보수를 취한 2진수 값을 출력하는 코딩인데 왜 a에 12라는 양수가 저장되어 있냐고 이상하다고 생각하실 수 있습니다. 그 이유는 12라는 숫자를 기준으로 보수를 취하기 때문에 -12를 코딩에서는 선언할 수 없습니다. 1비트씩 쪼개서 배열변수에 넣는 거라서 양수 12를 기준으로 2의 보수를 취해 배열변수에 -12의 결과같을 얻도록 하기 위한 표현임으로 감안하셔서 보시기 바랍니다.
[결과]
마무리
문득 떠오른 2의보수에 대한 C언어 코딩을 해 보았네요. 참고로 전체소스를 보면 꽤 긴 코딩이 이루어졌습니다. 중간 중간 결과를 printf()문으로 출력하다보니 불필요한 코딩이 많아졌는데 최종결과만 출력하게 수정하여 코딩을 줄여서 깔끔하게 정리해서 보시기 바랍니다.
