C 프로그래머가 알아야할 것들 - Chapter 2. 비트의 법칙

김성훈 (sunghun84@nate.com)

Chapter 2. 비트의 법칙

(1) 비트가 뭐지?

(2) 프로그램 작성하는데 비트가 왜 필요한걸까?

(3) 데이터형

(4) 바이트로 구성된 파일

(5) 비트 연산자

(6) 간단히 구현해보는 압축


(1) 비트가 뭐지?

비트란 Binary Digit. 즉 이진수의 약자입니다. 한마디로 이진수를 의미한다고 할 수 있죠. 비트는 컴퓨터에서 제어 가능한 데이터의 최소단위입니다. 하지만, 컴퓨터에서 입출력할때 사용하는 최소 단위는 바이트죠. 둘다 최소단위인데...저게 뭔소린가...하실분도 있을겁니다.

간단히 설명하자면, 비트란 저번 강좌에서 배웠던 이진수 10을 2비트(2진수 2자리 수이기에)로 표현 가능하고 제어 가능하단 의미고, 바이트는 비트 8개가 모여서 구성된 것이 1바이트로, 파일이나 데이터형의 최소단위로 쓰입니다.

(2) 프로그램 작성하는데 비트가 왜 필요한걸까?

많은 분들이 프로그램을 만드는데 왜 비트가 필요한지 의문을 가지실거라고 생각합니다.
그런데, 위에서 설명했듯이 데이터의 최소단위는 비트입니다.

최적화 된 프로그램이란 메모리와 속도 모두 만족 시키는 프로그램을 말하는데, 그것을 만족하기 위해선 비트 단위 연산 또는 처리가 필수이기 때문입니다.

하드웨어의 발전에 따라 빠른 속도보다는 쉬운 사용법과, 유지 보수 또는 코드 재사용이 쉬운 프로그램이 인기를 끌고 있는건 사실입니다.

하드웨어가 발전함에 따라 그 하드웨어의 기능을 활용하기 위한 기술이 적용되다보니 여전히 빠른 프로그램을 작성할 필요성은 존재합니다.
메모리와 비트 단위 연산 권한이라는 강력한 기능을 부여받은 이상 비트에 대해 알아두는 것은 당연하다고 할 수 있습니다.

(3) 데이터형

C언어에서는 다양한 데이터형을 제공합니다.
여기서는 주로 사용되는 몇 개의 데이터형만 가지고, 비트와 관련해 알아보도록 하죠.

흔히 문자형으로 알려진 char (캐릭터형)는 1바이트로 이루어져있습니다.
일반적으로 1바이트=8비트이므로, 0000 0000 이렇게 8자리 2진수만큼 사용할 수 있는데, 2의 7승은 256 (첫 자리가 2의 0승이므로, 8비트의 경우 2의 7승만큼 사용 가능합니다.)
이므로, 부호가 없는 경우는 0~255, 부호가 있는 경우는 -128~127(C표준에서는 -127까지 보장해준다)까지 사용 가능하게 되는겁니다. 부호가 있는 경우는 최상위 비트를 부호 비트로 사용하게 되므로 사용 가능한 수의 범위가 반으로 줄 게 됩니다.

2바이트 데이터형인 short int 도, 2의 15승인 65536만큼의 수를 사용할 수 있는데, 부호 없는 경우 0~65535, 부호가 있는 경우 -32768~32767까지의 수를 사용할 수 있는거죠. 32비트 데이터형도 마찬가지로 2의 31승만큼 사용 가능하다고 알고 계시면 됩니다.

데이터형에 따른 사용범위는 곧 대중화될 예정으로 알려져있는 64비트 운영체제에서 주로 사용될 64비트 데이터형도 마찬가지겠구요.

(4) 바이트로 구성된 파일

비트 8개가 모여서 만든 바이트가 모여서 만들어진 것이 파일입니다.
우리가 흔히 사용하는 이미지 파일들도 알고보면 색상 정보를 담고 있는 바이트의 집합입니다. 여기서 조금 부연 설명을 하자면, BMP(비트맵)파일의 경우는 헤더나 컬러 테이블 정보도 담고 있긴하지만, 일반적으로는 RGB색상값만 가지고 있다고 보시면 됩니다. RGB 색상 값은 Red 1바이트, Green 1바이트, Blue 1바이트씩 저장됩니다.

색상값을 가지고 있다가 프로그램에서 BMP파일을 읽어들였을 때, 색상 정보를 읽어서 RGB색상값을 조합한후 점을 찍어서 (BitBlt함수로도 찍을 수 있는데라고 생각하실분도 있으시겠지만, 그 함수도 결국 내부적으론 점을 찍어서 표현해줍니다.) 그 색상을 모니터에 표현하도록 명령을 내려주기 때문에, 우리 눈에는 컬러 이미지를 볼 수 있는겁니다.

저장되어 있는 RGB색상값을 아무런 압축도 하지 않고 모두 가지고 있는 경우가 위에서 설명한 BMP파일 포맷이고, JPG의 경우는 고도의 압축 기법(압축률도 지정가능합니다)을 통해서 용량을 줄였지만 결과적으로는 색상값을 가지고 있다 신장(압축해제)후 화면에 뿌려주는 원리는 비슷합니다.

벡터 그래픽 파일의 경우에는 점,선,곡선등의 정보를 저장하고 있는 포맷이지요. 그래서 화면에 축소나 확대에서도 같은 이미지를 볼 수 있는것이지요.

동영상 파일도 많은 양의 그림 정보를 담고 있다가, 1초에 몇번 이상(1초에 몇 번 화면이 갱신되는지를 프레임이라고 하는데, 초당 24내지 30프레임은 되어야 깜빡임이 사람 눈에 보이지 않는다고 합니다. 일반적으로 모니터의 경우는 60번 이상 갱신되고 있죠)갱신되는지에 따라 그것을 재생시켜줍니다.

음악파일도 마찬가지로, 소리 정보를 디지털값(수치값)으로 가지고 있다가, 그 정보를 재생시간에 맞춰 재생하는 방식을 취하고 있죠.

스타크래프트 리플레이 파일의 경우에도 비슷하게 첫 위치값을 저장한후에 거기서 변화한 값과 내린 명령,시간값들을 저장했다가, 리플레이 메뉴에서 재생시 그 정보를 바탕으로 게임을 재생시키는 것이지요. 그래서 리플레이 파일의 용량이 그다지 크지 않은것입니다.

게임 세이브 파일의 경우에도, 그 캐릭터의 레벨, 무기 일람, 체력, 공격력, 방어력 등의 파라미터와, 그 캐릭터의 현재 위치, 플레이 시간 등의 정보를 저장하고 있습니다. 물론 에디트가 힘들 게 하기 위해 단순한 파일 구조(순차적)으로 구성하지 않는 경우가 대부분이긴하지만요.

모든 데이터는 바이트 단위로 저장된다는 것. 그 바이트를 구성하고 있는 것은 비트라는 것 이것이 핵심입니다.

(5) 비트 연산자

자 비트에 대해 배웠으니 비트 연산을 한번 해봐야겠죠?
비트연산은 부울대수를 배우셨던 분들은 매우 친숙하실겁니다.

비트연산에 사용되는 비트연산자란 논리 곱 (&) , 논리 합 (|), 논리 부정 (~), 베타적 논리합(^)이 있습니다.
여기서 시프트 연산자 좌측 시프트 (<<) 우측 시프트 (>>)도 있죠.

논리곱은 둘다 1일 때만 참(1)이 됩니다.

1 & 1 = 1
1 & 0 = 0
0 & 1 = 0
0 & 0 = 0

논리합은 둘중에 하나라도 1이면 참(1)이 됩니다.

1 | 1 = 1
1 | 0 = 1
0 | 1 = 1
0 | 0 = 0

베타적 논리합은 두수의 값이 달라야만 참(1)이 됩니다.

1 ^ 1 = 0
1 ^ 0 = 1
0 ^ 1 = 1
0 ^ 0 = 0

논리 부정은 0은 1로, 1은 0으로 만들어줍니다.

~1 = 0
~0 = 1

이 되는 것이죠.


좌측 시프트 연산자는 비트를 왼쪽으로 옮겨주고, 빈자리엔 0을 넣어줍니다.

0011 0010 << 2

이 연산후에 0011 0010 (10진수 50)에서 1100 1000 (10진수 200) 로 바뀝니다.
왼쪽으로 2번 이동했더니 수가 4배가 되었죠?
잘 보시면 시프트 연산자 한번당 수가 2배가 된다는 것을 아실수 있을겁니다.


우측 시프트 연산자는 비트를 오른쪽으로 옮겨주고, 빈자리엔 0을 넣어줍니다.

0011 0011 >> 2

이 연산후에는 0011 0010 (10진수 50)에서 0000 1100 (10진수 12) 가 되었습니다.
좌측 시프트 연산자와 마찬가지로, 우측으로 2번 이동했더니 수가 4분의 1이 되었죠? (12.5여야하지만, 소수점 이하는 버립니다)


(6) 간단히 구현해보는 압축

압축방법에는 런 렝스 코드, 허프만 코드등 다양한 방법이 있는데요, 여기서는 시프트 연산자와 비트 연산자의 조합으로 간단한 압축을 구현해보겠습니다.

아까 데이터를 압축하려면 현재 데이터에서 변화한 정보를 담는 것이 좋다고 했었죠?

그 원리를 이용하는 것입니다.

주로 다른 파일보다는 이미지, 음악 파일, 동영상 파일등에 사용되는 데이터 압축의 원리는 이 바이트를 기본으로 한 데이터들이 비트로 이루어져있다는 것이 핵심입니다.

어떤 데이터든 현재 상태와 다음상태의 값을 모두 가지고 있는 것보다 현재값 (초기값 또는 현재값은 모든 데이터를 기록해둬야 합니다)을 기록해둔후 차후에 변화되는 값을 저장하게 되면 적은 용량으로 데이터를 기록할 수 있을겁니다. 일반적으로 한 픽셀값은 1바이트로 저장된다고 얘기했었죠? 그런데 방금전 픽셀값은 10이고 다음 좌표값은 30이면 20만 저장하는 것입니다. 그렇게 되면 6비트 (2의 5승이 32이니, 0~31까지 사용가능)내에 데이터를 담을 수 있습니다. 그리고 나서 좌측 시프트 시키면 하위 2비트에 0이 들어오겠죠? 그 2비트에 다른 정보를 담게 되면 전체적으로 용량이 줄 게 됩니다. 이것이 바로 데이터 압축의 원리죠.

+ Recent posts