| ||||
| ||||
============================================= Bit 를 이해하자 # 1 4 Dec, 2002 Written by Un-Wook ============================================= - 차례 - 1. 서문 2. 주제 3. ON 과 OFF 밖에 모르는 컴퓨터 4. 비트들의 묶음 5. char 형에 대한 오해 6. 진법에 대한 오해 7. 음수의 표현방법 8. 마치며 ----------------------------- 1. 서문 ----------------------------- 또 강좌를 하나 써봅니다. 이번에 쓰는 강좌는 프로그래밍 경험이 적으신 분들이 꼭 알아야 할만하다고 생각해서 써보는 것이구요.. 저번에 썻던것처럼 읽기 쉽게 쓸겁니다.. (안쉬웠다구요?? ㅠ_ㅠ) 이번에도 자세하게 풀어서 려니까 또 글이 좀 길어질 것으로 예상됩니당.. 제가 요즘 게시판에서 답변을 많이 하고 있는데.. 진법 변환의 의미를 오해하시는 분들도 종종 계시고.. 텍스트와 바이너리의 구분이 모호하신분도 있고 .. 베이직 하시다가 C 언어로 넘어오신분들은 스트링에 대해서도 혼동 많이 하시더라구요.. 그래서 그런것을 좀 누군가가 정리해 놓을 필요가 있을것 같아서 강좌를 써봅니당.. 제가 이 강좌에 다룰 범위는 전산학에서 말하는 자료처리의 기본이라고 보셔도 됩니당.. 비트라는 단위를 이해하지 못하는 사람은 최적 로직구현이라던가 최적 패킷디자인, 최적 포맷디자인 등 등.. 많은 면에서 비트를 이해하는 사람에 비해 열등합니다.. beginner 분들을 대상으로 쓰는 글이고... 전 절때로 유식한척하면서 강좌 쓰지 않으니 안심하셔요.. 저 역시 그런거 모르던 옛시절이 있엇고.. 다 많이 접하고 부딪치면서 알게 된거고, 누구나 학습하면 이해할 수 있는 내용입니다.. C 언어가 고급언어라고는 하지만, 저급언어의 특성도 상당부분 갖고 있고.. (그것이 C의 이점입니다.) 중요한 것이니 꼭 한번 읽고 생각해 보셔요.. beginner 를 대상으로 쓴 글이라고는 했지만 프로그래밍 경험이 조금 있으셔야.. 이 글이 가슴에 와닿을 것 같습니다. 그럼 시작해 보겟습니다. ------------------------------------- 2. 주제 ------------------------------------- 이 글의 주제는 제목에서 짐작 하실 수 있듯이 Bit에 대한 설명입니다. Bit가 무엇인지, 어떤작용을 하는지 이해하고 아울러 비트 단위의 연산과, 최적화된 데이터 프로그래밍 기법에 대하여 다룰 예정입니다. 그 비트가 정우성이 나오는 비트가 아니구.. 또 다른 비트 입니다. 정우성이 나오는 비트는 Beat 에요 .. 썰렁했나요.. ㅋㅋㅋ ------------------------------------- 3. ON 과 OFF 밖에 모르는 컴퓨터 ------------------------------------- 베이스 설명을 좀 깔아보겟습니다. 별로 안어려워요.. "컴퓨터는 2진법을 사용한다" 라는 말을 어디선가 참 많이많이 들어보셨을 겁니다. 하지만 프로그래밍을 하면서도 그 의미가 익숙하지 않으실 것입니다. 우리는 고급언어를 사용하여 프로그래밍을 함으로 2진에 대한 의미를 이해하지 못해도 프로그램 하나 뚝딱 짜는데는 무리없는것도 사실입니다. 그래도 그 의미는 알아야 할 필요가 있어요.. 컴퓨터는 전기들어감(ON)과 전기나감(OFF)만 가지고 모든 수치와 데이터, 그리고 실행코드까지 인식합 니다. 2진법이라고 하는 것은 그냥 사람이 편의상 그렇게 부르는 것이고.. 컴퓨터는 2진법이고 뭐고 몰릅니다. 그냥 ON과 OFF로만 처리합니다. 그 동작이 (산술연산부분이) 마치 2진법과 유사하여 2진법 이라고 부르는 것입니다. ON은 1 이고.. OFF는 0 으로 생각하는 것이지요. 전기 들어감.. 전기 나감.. 이것 하나하나가 Bit 입니다. OFF ON ON OFF 이렇게 비트가 4 개가 있으면.. 이것은 사람이 이해할때 이진법으로 0110 라고 생각할 수 있습니다. 이것은 우리가 초딩때부터 세뇌돼듯이 학습해온 10진법으로 생각하면 6 이라는 수치가 될 수 있습니다. 아직은 좀 애매.. 하죠? 아래 코드를 보세요.. char cA= 6; printf("%d", cA); 결과는?.. 당연히 화면에 6 이 출력되겠지요 ㅋㅋㅋ 이것은 컴퓨터가 6 을 이해하는것이 아니라 메모리 어딘가에는 00000110 이라는... (OFF OFF OFF OFF OFF ON ON OFF) 전기적 시그널이 들어가있고 printf() 라는 함수가.. 화면에 그냥 그에 해당하는 글꼴을 출력하는 것 뿐입니다. 컴퓨터는 이처럼 아무것도 아닌것처럼 보이는.. "비트"라는 것을 가지고 모든 것을 처리합니다.. 동영상, 이미지, 음성, 스트링 등등등.. 그밖에도.. 디지털밥통, 디지털 냉장고, 디지털 카메라.. 디지털이라고 불리우는 가전기기들도 모두 이러한 비트라는 개념을 이용합니다. 메모리(RAM)라면 전기적 시그널을 사용하고, 디스크라면 자기적 시그널을 사용합니다. ----------------------------- 4. 비트들의 묶음 ----------------------------- 컴퓨터는 비트를 이용하여 모든 것을 처리한다고. 위에서 간략하게 설명했습니다. 비트는 수치(숫자)를 의미하며.. 컴퓨터에서 모든 것은 결국엔 숫자 놀음입니다. 그것을 해석하기에 따라 이미지가 될수도 있고, 스트링이 될수도 있고, 음성도 될 수 있습니다. 그런데 이 비트라는 것은 하나만 가지고는 수치를 의미하지 못하지요. 단지 1 과 0 밖에 안됩니다.. (ON 과 OFF) 좀더 큰 수치를 표현하려면.. 비트를 복수 단위로 다뤄야합니다. 요즘 나오는 CPU와 OS들은 기본적으로 메모리에서 32 단위로 비트들을 억세스 합니다. (그래서 32비트 CPU라느니 32비트 플랫폼이니 하는 말이 있는 거구요.) 비트가 32개 있으면.. 각 비트들의 ON OFF 를 통해서 00000000000000000000000000000000 부터 11111111111111111111111111111111 까지 총 4294836255 가지의 경우의 수가 발생합니다. 굉장한 수치이지요.. 이것이 32비트로 표현할수 있는 최대 범위 입니다. 이것은 곧 32비트 OS 에서 선형으로 접근할 수 있는 최대의 메모리 량이구요 8비트를 1바이트라 합니다. (이유가 뭐냐구요? 그냥 규약입니다.) 우리가 1바이트가 어쩌고 저쩌고 하는게.. 이 1바이트가.. 8 개의 비트로 구성되어 있습니다. 16비트는 2바이트이고 32비트라면 4바이트가 됩니다. 이것을 어셈에서는 워드형(16비트), 더블워드형(32비트)라고도 부릅니다. 32비트는 너무 크니까 8비트를 가지루 주로 설명하겠습니다. ----------------------------- 5. char 형에 대한 오해 ----------------------------- 베이스루 깔아야할 설명은 이쯤하면 됐다 싶구.. 이제부터는 C 언어에서 지원되는 자료형을 가지구 설명하겠습니다. char 라는 데이터 타입이 있습니다. 이것을 문자형이라고 설명하는 C언어입문서적이 있은데 좀 잘못된 표현이 아닌가 싶습니다. 입문자 입장에서는 혼동이 많이 된다고 생각되요.. 문자형이라고 하니까 char에는 문자가 들어가는 것처럼 뉘양스가 느껴지잖습니까.. char는 그냥 8비트 정수형 타입입니다. 비트를 8개 사용하고 정수 값을 취합니다. 컴퓨터는 문자를 모른다니까요.. 모든 것이 2진 수치입니다. char 는 8비트 정수형 타입입니다. 비트가 8 개이고.. 00000000, 00000001, 00000010, 00000011, 00000100, 00000101 ~~~ 11111111 까지 이런식으루 256 가지의 경우의수를 나타낼수 있는 수치형 데이터 타입입니다. 아마도 char cA= 'A'; 이런것 때문에 char 가 문자형이라고 설명하는 것 같은데요.. 그렇다면 int nA= 'A'; 도 되니까 int도 문자형이라고 봐야하나요?.. 그건 아니라고 봅니다... 작은따옴표 안에 있는 것은 아스키코드가 정수값으로 변환된다는 것을 의미하는 것이며 컴파일러가 소스를 컴파일할때 'A'를 보구 'A'에 해당하는 아스키 코드인 65 라는 수치값으로 변환해서 대입해주는 것입니다. 정수를 대입한다는 것이죠. 문자형이라는 것은 편의상 그렇게 부르는 것이지.. CPU 내부에서는 문자형이란 것은 존재하지 않습니다. 모든 것이 0 과 1 입니다. (단지 그 수치가 코드테이블에 매칭하는 과정을 거치면 문자를 의미하게 되는 것입니다. ) (참고로 요즘은 8비트 확장아스키코드를 사용합니다.) (2편 강좌에서 자세하게 설명할께요) ----------------------------- 6. 진법에 대한 오해 ----------------------------- 아래 코드를 보아주세요. char cA= 0x0F; char cB= 15; 진법개념에 대해서 모호하신 분들을 위해서 설명하는 내용입니다. cA 과 cB 는 똑같이 15 라는 값입니다. 이 15 라는 것은 사람이 이해하는 수치고 정확히 컴퓨터 입장에서 표현하자면 00001111 이 됩니다. 단지 컴파일러가 컴파일할때 소스파일에서 "0x0F" 나 "15" 라는 것을 00001111 로 바꿔서 EXE에 들어갈 네이티브 코드를 만들어 주는 것입니다. 컴퓨터는 진법을 모릅니다.. 그냥 전부 비트를 사용한 2진법입니다.! 위의 코드에서 변수 cA와 cB 둘다 00001111 입니다. 우리가 코딩할때 16진법 10진법 그런것을 사용하는 것은 컴파일러 제작에 참여한 프로그래머들의 노력 의 결실입니다. 2진을 가지고 그렇게 동작하도록 만들어 놓은것입니다. 우리는 고마워해야 되요.. 정리해보면.. 코딩할때 사용되는 진법은 별 의미가 없다는 것입니다. ----------------------------- 7. 음수의 표현 방법 ----------------------------- 이 부분은 제가 쓸 강좌 내용과는 좀 멀긴하지만.. 참고하시라고 써보겠습니다. char가 8개의 비트를 사용하는 데이터 타입이고 256 가지의 경우의 수를 갖을 수 있다고 설명했습니당 .. 그런데 우리가 양수만 쓰나요. 음수도 쓰잖아요.. 그래서 생겨난 개념이 signed 와 unsigned 입니당.. 음수값을 표현하기위해 있는 것입니당.. (signed: 음수부호있는, unsigned: 음수부호없는) 그냥 char 라고 선언하면 그것은 signed 가 되구요 unsigned로 선언하시려면 꼭 앞에 unsigned 를 달아주셔야 합니다. unsigned char 이런식으로 선언해야지요.. signed 와 unsigned 가 동작하는 차이는 아래를 보시면 이해가 빠르실겁니다.. char cA; // 8 개의 비트를 사용하고.. 최상위(첫번째) 비트는.. 음수/양수 여부 판별 // 표현범위는 -128 ~ 0 ~ 127 unsigned char cB; // 8 개의 비트를 모두 양수로 사용 (0도 포함) // 표현범위는 0 ~ 255 unsigned 와 signed 의 차이는.. 음수를 사용할 것인가의 말것인가의 차이입니당.. signed 에서는 8 개의 비트중 최상위 비트를 부호 판별용으로 사용하고, 8 개의 비트로 음수와 양수를 모두 표현하려니.. 최대 수치가 그만큼 줄어듭니다. unsigned 로 선언하여 음수를 사용하지 않으면.. 좀더 큰 수치를 표현할 수 있기 때문에 그만큼 이득이 지요.. 그리고 음수 처리시에는 2의 보수법이니 뭐나 하는 규칙이 들어가는데 그것 까지는 구지 모르셔도 됩니당.. 그리고 거기까지 설명이 들어가면 강좌의 방향이 삼천포로 빠질까 바.. 제가 말하려고 한 것은 단지 signed 와 unsigned 라는 게 있다.. 이정도 이고. 비트와 연관이 된 내용이라 잠깐 설명해 보앗습니다. 실수를 표현하는 법도 조금 독특한데.. 그것도 다루지 않겠습니다. ----------------------------- 8. 마치며 ----------------------------- 오늘 아침에 방값 밀린거 내라고 집주인이 찾아와서 집중 못해서 쓴것 같네요.. 한번에 너무 길게 쓰면 읽는분도 피곤하실테니 다음편을 기약하겠습니다.. 오늘은 비트의 개념을 설명해드리는 것에 포커스를 두었고.. 다음편 강좌에서는 비트를 쫌만 더 설명하고 실제로 비트를 가지고 연산하고.. 비트를 쪼개서 쓰면서 효율적으로 프로그램을 작성하는 기법을 소개하겠습니다.. 끝까지 읽어주셔서 감사하고.. 수고하셨습니다. 마침. | ||||
|
| ||||
| ||||
============================================= Bit 를 이해하자 # 2 4 Dec, 2002 Written by Un-Wook ============================================= - 차례 - 1. 서문 2. 문자를 모르는 컴퓨터 3. 문자열도 모르는 컴퓨터 4. 텍스트와 바이너리의 차이점 5. 마치며 ----------------------------- 1. 서문 ----------------------------- 첫 회에서는 비트에 대해서 감을 잡을 수 있도록 설명했다면 이번에는 전편 강좌보다는 조금이나마 상위레벨적인 내용을 다뤄보려합니다. 상위레벨과 하위레벨이란 난이도의 차이를 말하는 것이 아닙니다. 기계에 접근한 것일수록 하위레벨(Low Level Layer)이라고 칭하고.. 사람의 수준으로 접근한 것일수록 상위레벨(High Level Layer)이라고 합니당.. 난이도의 차이가 아닌 "계층"의 차이랍니다.. 로우레벨루 갈수록 이해해야할 것이 많고 복잡하고 어려워져요.. 그래서.. 로우레벨을 이해하고 다루는 사람일 수록 인정 받을 수 있구여.. 난관이 닥쳐도.. 원리를 이해하고 있기때문에.. 남들에 비해 쉽게 해결해 나갈 수 있지효.. 우리 모두 열씸히 겅부해서 실력을 키워갑시당.. 잡설은 그만하고.. 시작해보지요^^ ------------------------------------- 2. 문자를 모르는 컴퓨터 ------------------------------------- 전편강좌에서 컴퓨터는 2진화되어있는 1과 0밖에 모른다고 했습니다. 그런데 우리는 프로그래밍할때나.. 컴퓨터를 그냥 사용할때나.. 문자나 문자열 입력하고 출력하는게 당연한거거덩여.. 하지만 컴퓨터는 문자라는 것이 뭔지 모릅니다. 이번 단원에서는 그 문자 표현에 대한 원리를 맛뵈기로나마 파해쳐보면서 설명해 드리려고 합니다. 아스키 코드 테이블이라는 것이 있습니다.. 아스키 아스키 아스키... 어디선가 많이 들어보셨지요? 1편 강좌에서 잠깐 얘기가 나오기도 하였고, 프로그래밍을 해오시면서 은연중에 많이 들으셨을 것입니다. 요놈이 무엇인가 하면.. "각 수치에 해당하는 문자를 정의해둔 규약입니다!" 이거만큼 간결하게 아스키코드를 설명할 말은 없을듯 ㅋㅋㅋㅋ 어쩜 여기까지 읽다가 벌써 눈치 까신분도 있을지도 모릅니다. 예를들어 숫자 65 는 A 라는 문자를 뜻하고.. 숫자 66 은 B 라는 문자를 뜻하고.. 바로 요겁니다.. 아스키코드 라는게.. ### 여기서 첨부된 그림을 봐주세요 ### 이런 규약이 정해져 있는 것입니다. 문자 A 를 화면에 찍으려면.. 65 이라는 값을 가지고 폰트 데이터에서 65 번째 인덱스에 있는 폰트를 그냥 화면에 찍는 검니당.. 65 번째 인덱스에 있는 폰트가 Z 같이 생긴 폰트라면 A 가 아니찍히구 Z가 화면에 찍혀버립니다. 컴퓨터는 문자를 모른다는 것입니당... 다시한번 강조하지만.. 컴퓨터는 오로지 수치 놀음이고.. 그 수치는 2진화 되어있습니다. 'A' 과 'A' 가 같은것인가 비교하는 것도 결국에는 65 와 65 를 비교하는 것입니다.. 컴퓨터 입장으로 좀더 다가가서 말하자면 10000001 과 10000001 을 비교하는 것이에요. (이 수치를 비교하는 것 자체는 CPU 명령에 있구요) 이 강좌를 읽기전까지 아스키코드가 무엇인지 모르셨다면.. 아하~~ 하실것 입니당. (아하~ 해주세요 ㅠㅇㅠ) 표준 아스키 코드에는 0 부터 127 까지 128 개의 의미를 갖는 코드를 정의 해 놓았습니다. 여기엔 알파뱃도 들어가있구요 숫자도 들어가있고 이상한 문자도 있고 특수 코드도 있습니다. 1 바이트는 256 가지의 수를 표현 가능하다고 말했는데.. 왜 128 개 밖에 없냐구요? 좋은 질문 하셨습니다. (혼자 북치구 장구치는거 같네 ㅡㅡ) 원래 표준 아스키 코드는 7 비트입니다. 그래서 128 개 까지만 정의되어있지요. (7 비트로는 128 가지의 수치가 표현되기때문) 근데 요즘 사용하는 아스키 코드는 8 비트루 이루어진 "확장 아스키 코드"라는 것을 사용합니다. 8 비트로는 256 가지가 사용가능함으로.. 확장 아스키코드에서는 256 개의 코드가 정의 되어 있습니다. 127 번째 이후 코드들은 규격이 전부 제각각이었는데.. 요즘엔 거의 표준화 되어있는 상황이랍니당.. 우리가 쓰는 아스키코드는 "확장 아스키코드"라는 것을 알아두셔요. 이런 코드는 어디서 만들엇냐면요.. 표준 위원회들이 많습니다. ANSI 라는 협회도 그런 협회이고, IEEE 도 있고.. 여턴 뭐 하나 표준 규약 정하는데 지네들끼리 싸우고 난리 지랄도 많댑니다. 아스키는 ANSI 에서 규정한 거일껄요?? ------------------------------------- 3. 문자열도 모르는 컴퓨터 ------------------------------------- 컴퓨터가 문자도 모르는데 문자열(스트링)을 알기나 하겟습니까.. ㅋㅋㅋ 이 단원에선 설명할께 별로 없을것 같군요.. 스트링은 그런 아스키 코드들이 연속으로 이루어진 메모리이구요.. (2진 수치이지요) C언어에서 다룰때는 포인터를 이용하지요. char *p= "ABCDEFG"; 위와 같은 코드는 프로그램 실행시에 "ABCDEFG" 라는 것을 의미하는 아스키코드배열이 메모리 어딘가에 있는데 이 메모리의 시작주소값이 p라는 변수에 대입되는 것입니다. (제가 배열이라고 했지만 배열은 아닙니다. 이 부분에 대해선 다음에 다른 강좌를 또 쓸 계획입니다..) 베이직에서 C 언어로 넘어오신분은.. C언어에서 왜 문자열을 비교할때 strcmp() 등을 사용하는지.. 감이 잡히실 겁니당.. 베이직 언어는 문자열 끼리 바로 비교가 가능한데.. C 언어에서 하려니 그게 안되거덩요.. C 는 고급언어이면서 저급언어의 특성까지도 갖춘 훌륭한 프로그래밍 언어입니다. 첨에는 이해가 잘 안되도.. 익숙해 지시다 보면. 막강한 동작이라는 것에 감탄하실겁니다. 컴퓨터는 문자열이라는 데이터 타입을 다루지 못하며, 포인터를 이용하여 그것을 처리합니다. 포인터는 하나의 변수이고, 그 변수에는 메모리 주소값이 들어가있는데.. 메모리 주소값을 서로 비교를 하니.. 문자열은 같아도.. 서로 다르다는 판정이 나오는 것입니다 그래서 strcmp()를 이용해서 실제 메모리에 담긴 값을 비교한 결과를 얻어오는 것입니다. strcmp() 는 명령어가 아닙니다. 함수입니다. 베이직에서는 대부분의 동작이 내부 명령어로 되어 있는 반면 C언어에서는 CPU의 기본 동작만을 가지고.. 그것을 함수로 만들어 라이브러리화 해놓읍니다. 이 얼마나 바람직한가요.. 그래도 C 언어가 저급언어의 특성을 가진 것이 뭐 그리 대단하냐... 라고 물으신다면 컴퓨터에서 표현할 수 있는 모든 동작을 구현할 수 있고, 제한이 두어져있지 않은 언어라는 것입니다.. 컴퓨터를 깊이 이해할 수도 있구요.. C++로 와서는 클래스라는게 있어서 코드의 고차원적인 추상화 및 계층화가 가능합니다. 여튼... 그리고 문자열에서는.. 맨 마지막에 문자열이 끝날지점에 0 이라는 값이 들어갑니다. (아스키 코드에서도 0 번째 코드도 NULL 이라고 규정지어져있습니다.) 안그러면 컴퓨터가 멍청해서 문자열이 어디서 끝나는지 모르거든요.. 컴퓨터가 모르는건아니고.. 컴파일러가 생성한 네이티브코드에 따라서 좀 차이가 납니다.. 참고로... 파스칼의 경우는 문자열 끝에 0 이 안들어가고 문자열 맨 앞에 몇글자로 이루어진 문자열인가하는 정보가 옵니다. ------------------------------------- 4. 텍스트와 바이너리의 차이점 ------------------------------------- 이제 비트와 문자, 문자열에 대해서 대충 감이 잡혀가시나요?.. 이해가 잘 안오면 이부분 읽지 마시구.. 위에 부분 한번더 읽어보세요.. 되도록 쉬운말로 작성한 글이라 반복적으로 읽다보면 이해가 오실거라고 믿어요.. 우리가 프로그래밍하면서 텍스트니.. 바이너리니 하는 말을 많이 듣고 많이 사용합니다. 컴퓨터가 파일을 다룰때 정말로 텍스트, 바이너리... 이렇게 구분하는 것일까요?. 아닙니다. 컴퓨터는 뭐가 바이너리고 뭐가 텍스트인지 모릅니다. 단지 0 과 1 이라는 비트들의 연속으로 이루어진 하나의 덩어리가 디스크 상에 존재하는 것이 파일이란 것입니다. 그 0 과 1 의 ON,OFF 는 자성의 성질을 이용하여 시그널되어 있구요. 프로그래머는 그냥 수치들이 쭈우우욱 배열되어있는 거라고 생각하시면 됩니다. 바이너리와 텍스트의 구분은 없습니다. 그냥 전부 바이너리라고 보면 됩니다. 그것을 구분하는것은 우리의 몫이죠.. 어떻게 로드하느냐 혹은 어떻게 기록하느냐에 따라서 텍스트 포맷이 될 수도 있고 바이너리 포맷이 될수도 있습니다. 단지 차이점이라면 MS계열 운영체제에서의 텍스트 파일은 줄내림의 의미가 2개의 코드, 즉 2 바이트라는 것입니다. (아스키코드에 줄내림 코드가 있습니다) 왜 두개의 냐구요?.. 행 처음으로, 행내림의 의미인데. 아마 프린터 기기의 처리를 염두해서 그렇게 한것 같습니다. "케리지 리턴"과 "뉴 라인" 라고 부르는데요 하나는 줄의 처음으로 가고 하나는 줄을 내립니다. C언어에서 프로그래밍할때 \r 과 \n 이 그것을 의미합니다. \r 은 아스키코드값 13 이고 (0x0D) \n 은 아스키코드값 10 입니다. (0x0A) ----------------------------- 5. 마치며 ----------------------------- 아침에 닥달하던 집주인 생각을 잠시 잊고 연달아 2회분 강좌를 작성했습니다.. 던을 빨리 모아야할텐데 큰일이군요 ㅋㅋ 이번회에 비트의 연산까지 다뤄보려고 했는데.. 내용이 길어지면 한번에 읽기도 짜증나시니까 다음 회루 미루겠습니다.. 2회에서 설명한 내용은 컴퓨터가 2진 수치를 이용해서 문자와 문자열을 다루는 원리와 텍스트파일에 대해서도 알아보았습니다. 비트를 이해한 다는 것은 우리가 디지털 디지털.. 하는걸 이해하는 것입니다. 끝까지 읽어주셔서 감사하고.. 수고하셨습니다. 마침. | ||||
|
| ||||||||||||||||
|
| ||||
| ||||
============================================= Bit 를 이해하자 # 3 4 Dec, 2002 Written by Un-Wook ============================================= - 차례 - 1. 서문 2. 비트의 논리연산 3. 비트의 시프트 연산 4. 비트단위로 데이터를 최적화하는 예 5. 비트단위로 데이터를 최적화하는 기법 6. 마치며 ----------------------------- 1. 서문 ----------------------------- 아.. 슬슬 골이 아파오네요.. 이렇게 글을 길게 써본적이 없는지라 적응이 안되여 실은 지금 4회 강좌를 미리 써두고 나서 3회 강좌를 씁니다.. 3회라고 생각했던 내용이.. 별로 코딩할때는 도움이 안될것 같아서. 4 회로 미루고.. 3회에서 실용적으로 사용되는 기법들을 소개해보려고 합니다.. 이전 강좌들에서 비트의 의미를 이것저것 부연설명 해가면서 골터지게 설명했습니다. 컴퓨터에서 모든 것들은 결국에는 숫자 놀음이고, 그 숫자라는 것은 0 과 1 만을 사용한 2진화 되어있는 수치라고 말씀드렸습니다. 사실 컴퓨터(CPU)가 할줄 아는 것도 몇개 안됩니다. 명령어는 좀 많기는 하지만 결국에는 전송명령(복사), 사칙연산, 논리연산, 반복처리, 분기(쩜프&호출), 스택조작, 거의 이게 전부이고.. 그밖에 하드웨어와의 통신을 위한 입출력명령이라던지 그런것 들이잇어요 제가 쓰는 강좌는.. 전송, 사칙연산, 논리연산에 대한 내용입니당.. 이번 3회에서는 비트들의 논리연산에 대해서 설명하고, 직접 응용하는 기법도 소개해 드리려고 합니다. 어렵게 생각하지 마시구.. 이번에 설명할 내용은 실용적으로 사용하실 수도 있답니다.. 그럼 시작합니다. ------------------------------------- 2. 비트의 논리연산 ------------------------------------- 컴퓨터는 비트를 이용해서 모든 것을 처리한다고 말씀드렸고.. C언어에서도 비트를 다룰 수가 있습니다. 비트단위의 논리 연산등이 가능합니다. 비트를 논리연산해서 얻어지는 결과가 무어냐 물으신다면.. 못하면 손해본다고 말씀드리고 싶네여... 굳이.. 요약하자면 고급언어인 c언어에서 로우레벨틱하게 프로그램을 작성할 수 있고 데이터를 최적으로 접근하고 다룰수 있다고 설명드리겠습니다. 논리 연산에는 우리가 많이 알고있는 것중에는 NOT AND OR 가 있고 그외에 NOR 라던지 XOR 가 있습니다. 논리연산이라구 하면 if문과 같은 논리 분기에 사용되는 != && || 를 생각하실수도 있을텐데요.. 비트들의 논리연산에서는 연산자가 조금 다릅니다.. 순서대로 ~ & | 입니다. 그리고 CPU 차원에서 본다면 if문에 사용되는 논리식은 사실 분기(점프) 명령이라고 볼수 있고 진짜 논리연산이라고 하는 것은 비트들의 논리연산입니다. 비트들의 논리연산의 예를 들어보겠습니당.. 1 과 0 이라는 두비트를 and 연산하면 0 이 나옵니다.. or 하면 1 이 나오구요.. 굳이 설명할 필요가 없을것 같네여.. 1 은 전기시그널이 들어와있는 참이라는 값이고 0 은 거짓이란 값이라서 그래요.. 같은 식으로 not 과 or 도 이해되실거라고 생각해요.. 직접 사용할때는 이렇게 비트 하나만을 논리연산 하지 않고.. 바이트 단위로 논리 연산을 하게 됩니다. 예를 들면 10101010 과 01010101 을... 이렇게 두개의 바이트를 논리 연산하는 식을 많이 쓰지여.. 두 값을 or 하면 어떤 결과가 얻어질까요? 다 아시겠지만 정답은 아래와 같습니다. 10101010 01010101 ======== 11111111 각 비트들을 서로 or 해주면 사이사이에 모두 1 이 들어가 있어서 결과는 11111111 이 나옵니다.. C 코드로 쳐보면.. unsigned char cA= 170; // 이것은 이진수로 10101010 입니다 unsigned char cB= 85; // 이것은 이진수로 01010101 입니다. unsigned char cOrResult= cA | cB; 이 연산후 cOrResult 에는 255 라는 값.. 즉 11111111 이 들어옵니다. 이러한 동작은 우리가 알게 모르게 많이 사용합니다. 윈도우를 생성할때 스타일 값으루 WS_CHILD | WS_VISIBLE 이라고 넘겨주지요?.. 바로 그검니다. 저것이.. 비트의 논리 연산식입니다.. 그럼 다음과 같은경우에서 원하는 값만 추출해 보려면 어떻게 할까요? unsigned char cTest= 0x34; 저는 저 위에서 하위 4비트만 값을 뽑아보고 싶습니다. 그렇다면 이번엔 & 연산을 사용하심댑니당.. unsigned char cAndResult= cTest & 0x0F; cTest 라는 값과 0x0F 즉 00110100 과 00001111 이란 값을 and 연산하였기 때문에 하위 4비트의 값만 뽑아낼 수가 있습니다. 00110100 에서 하위 4비트만 뽑아내면 0100 을 얻어낼수 있지요.. and 비트연산도 꽤나 많이 사용됩니다. 좀 내용이 많을꺼 같아서 간략하게만 설명했는데..설명이 잘 된건지 모르겠네요.. 이해하셨을거라 생각하고 설명을 마칩니다.ㅋㅋㅋㅋ ----------------------------- 3. 비트의 시프트 연산 ----------------------------- CPU 명령중에는 비트 시프트 라는 것도 있습니다. 비트 로테이트라는 것도 있긴한데.. 그냥 시프트만 알아두셔두 될것 같아서 시프트만 설명하겠습니다. 00001000 이라는 수치가 있다구 치면. 이 비트들을 오른쪽으로 혹은 왼쪽으로 지정 횟수만큼 땡겨줄수가 있습니다. 00001000 를 오른쪽으로 2 번 땡겨주면 00000010 이 되지요? 이걸 다시 왼쪽으로 4 번 땡겨주면 00100000 이 됩니다. 쉽져.. 쉬워요.. 이게 비트 시프트 입니다. 이걸 코드로 쳐보면.. unsigned char cTest= 0x08; cTest= cTest >> 2; // 오른쪽으루 2 번 시프트 cTest= cTest << 4; // 왼쪽으루 4 번 시프트 이거도 마찬가지로 별설명 없어도 될 것 같습니다.. 단지 연산자를 >> 와 << 를 사용하는 것만 알아두심댑니다. 시프트할때의 효과가 무어냐면.. 오른쪽으로 시프트하면 시프트 횟수만큼 2의 곱절로 나눗샘이 됩니다. 오른쪽으로 두번 시프트 하게되면 나누기 4 가 되는 것인데 이게 그냥 나누기 4 가 아닙니다. 슈퍼 스피드 나누기4 입니다. 별도의 나누기 명령을 거치지 않고 바로 즉시 나누어진 값을 얻어옵니다. 2진수의 특성입니다 이런 것이.. 왼쪽으로 시프트를 두번 하게 되면 이것은 곱하기 4 가 됩니다. 이것 또한 슈퍼스피드 곱셈입니다. 덧셈 보다 빠른 곱셈입니다. 울트라 캡숑급이죠.. 과거 게임제작시에는 이러한 비트 시프트의 특성을 이용하여 고속 화면처리에도 썼습니다. 진짜 고속이거덩여... 그리고 기억나는 것이.. 옛날에 한글 출력 라이브러리를 제작하면서.. 조합형 비트맵 폰트 출력시에 각종 특수효과에(와각선, 그림자, 두껍게).. 비트시프트를 이용했습니다. 이용범위는 프로그래머가 응용하는 대로 무궁무진합니다. 단 비트 시프트를 이용한 곱셈 나눗셈에서는.. 시프트 되면서 날라가버리는 귀탱이를 염두해 두셔야합니다. 귀탱이가 짤려나가면서 오버플로우도 아닌 오버플로우가 발생하거든요. ------------------------------------------ 3. 비트단위로 데이터를 최적화하는 예 ------------------------------------------ 과거에는 1바이트가 정말 귀했습니다. 요즘에야 메모리도 방대해지고 OS 가 선형 메모리를 지원해줘서 백메가급 메모리 사용하면서도 메모리가 적다고 배부른 소리가 나오졍.. 한번에 64KB 이상 억세스하지 못하는 DOS 시절에는 진짜 1 바이트도 쪼개고 쪼개서 아껴썼거든요.. MSX 라던가 패밀리 같은 게임들 보면.. 게임 용량 많아봐야 16KB 그랬던 시절이 있엇습니다.. 비트단위를 사용하거든요,, 그때는 1메가 비트 게임이 초고용량 게임이엇지요. 100kb 정도가요.. 잡소리 집어치우구 본론 들어가겟씀당.. ㅋㅋ 요즘에도 비트를 분해하여 데이터를 처리하기는 합니다. 네트웤 프로그램에서 패킷 사이즈를 줄이기 위해서 비트단위로 빼곡빼곡 데이터가 들어가게끔 디자인 하기도 하구요. 요즘에도 종종 사용되는 16색 (16비트 아님) 비트맵 파일도 그럽니다. 1 바이트가 두 픽셀을 사용하지요. 16색은 비트맵 파일은.. 화면의 점 하나당 0~15 까지의 수치만 있으면 됩니다.. (파레트가 있음으로) 한마디로 4비트만 있으면 점하나 표현하기에 충분하다는 것이지요. 그래서 1바이트로 두개의 픽셀 정보를 담습니다. 아예 흑백 비트맵의 경우는 1 바이트로 8 개의 픽셀 정보를 담기도 합니다. 이러한 처리들이 전체적으로 데이터 사이즈가 작아지고, 컴팩드해지는 효과를 가져오지요. 가장 효율적이라고 알려진 허프만 압축 기법에도.. 비트에 대한 개념 없이는 접근하기가 힘듭니다. 저는 주로 사운드 프로그래밍을 해와서.. 2번에 걸쳐서 작곡 프로그램을 제작했었는데. 그때도 비트단위의 데이터 처리가 매우 이득을 주었습니다. 1 바이트에서 상위 3 비트는 명령코드와 하위 5비트는 그외의 정보.. 이런식으로 비트를 쪼개서 사용했고 데이터 파일이 많은 부가 데이터를 가지면서도 기존 음악 포맷에 비해 3/4 정도로 용량이 줄이는 성과를 냈습니다. 잡담인데.. 혹시 옛날에 사용되던 FM 음악 파일 아시는 분들 계시나요? ROL 파일이라거나, IMS 파일 최근에 나왔다가 요즘 안만들어지고 있는 SOP 파일.. ㅠㅇㅠ MP3 가 나오기전에 유행했던 음악파일 들이었거든요.. 6 년전쯤 까지만해도 이런 류의 음악 파일 제작이 활발했었는데.. 요즘은.. ------------------------------------------ 4. 비트단위로 데이터를 최적화하는 기법 ------------------------------------------ 다시 본론으로 들어와서 ㅡㅡ;; 어떻게 비트를 쪼개서 쓰냐면.. 비트의 논리연산과 쉬프트 연산을 이용합니다. 이미 설명한 내용이구요.. 조합해서 써보는 예를 보여드리겠습니다. 1 바이트를 가지고 2 개로 쪼개보겠습니다. 4비트, 4비트씩 쪼개보지요.. 쪼갠다는 말이 좀웃기네요.. 실실 쪼개다.. ㅋㅋㅋ 아시는 분은 아실만한 은어.. unsigned char cSrc= ????; char cData1= (cSrc&0xF0) >> 4; char cData2= cSrc & 0x0F; cData1 은 cSrc 에서 상위 4 비트를 뽑아내서 우측 쉬프트 4 번합니다. cSrc 가 11000011 이라면.. 이것을 0xF0 (11110000) 과 & 연산 한후.. 11000000 이 얻어집니다. 이 얻어진 값을 우측으로 4 번 쉬프트 하면 00001100 즉.. 1100 이라는 값이 얻어지는 것입니다. 우리가 원하던 첫번째 데이터가 얻어졌지요.. cData2 는 설명해 드릴필요 없겟죠^^; 반대루 두개의 4비트 데이터 두개를 1바이트에 넣으려면.. 이런 과정을 반대루 하면 됩니다.. & 연산 대신에 | 연산이 들어가겠지요. 비트를 이용하여 데이터를 최적으로 관리한다는 것이 이런 식이랍니다. 마지막으루.. 자기가 만든 프로그램은 용량 커야 한다고 생각하고 용량 불리실 계획을 짜구 계신분은.. 그런 생각은 버리셨으면 합니다. 일부로 용량 불리는건 좀.. 문제가 있지요.. 프로그램은... 최적의 메모리를 공간을 사용하면서 최적의 데이터들를 사용하고..(데이터의 크기) 컴팩트하면서 안정적으로 그리고 쾌속으로 작동하는 프로그램이 최고로 멋지고 잘만들어진 프로그램입니다. 요즘 쓸때 없이 용량만 큰 프로그램들을 보면.. 안타까울때가 많습니다. --------------------- 5. 마치며 --------------------- 하루동안에 너무 무리하면서 강좌를 다 쓰려고 하는건 아닌지 모르겟습니다. 빨리 하려는 생각에 강좌 질이 떨어지는 것 같기도 하고.. 졸음까지 오면서 정신이 흐려지네여 ㅡㅡ;;;;;; 제가 제대로 하고 있는 건지도 모르겟고 헤롱헤롱하네요... 그래도 지금까지 읽으셨다면, 비트에 대해서 감을 잡으신거고.. 비트를 응용하는 것에 대해서도 감을 잡으셨을 것입니다. 그럼 4 회를 읽어보세요.. 조금 깊숙하게 들어가서.. CPU 에 대한 설명을 조금 해보고.. 비트들을 이용한 덧셈처리과정을 이야기 해 보려고 합니다. 여기까지 읽어주신 것만으로도 감사드리고 수고하셨어요. 마침. | ||||
|
| ||||||||||||||||
| ||||||||||||||||
| ||||||||||||||||
|
| ||||||||||||||||
| ||||||||||||||||
| ||||||||||||||||
| ||||||||||||||||
| ||||||||||||||||
| ||||||||||||||||
| ||||||||||||||||
| ||||||||||||||||
| ||||||||||||||||
| ||||||||||||||||
| ||||||||||||||||
| ||||||||||||||||
| ||||||||||||||||
| ||||||||||||||||
|
'- 음악과 나 - > 『 짬 통 』' 카테고리의 다른 글
저수준제어를 이용한 wave재생 - 소스 , wavescope (0) | 2006.05.18 |
---|---|
사각영역에 숨겨진 작은 비밀 (0) | 2006.05.18 |
배열과 포인터는 전혀 다르다 (0) | 2006.05.18 |
알고리즘 강좌 (0) | 2006.05.18 |
시리얼통신의 깊은 이해 (0) | 2006.05.18 |