C프로그래머가 알아야 할 것들 - 01 진법

C프로그래머가 알아야 할 것들 - 01 진법

왜 진법에 대하여 배워야 하는가?

진법이란, 수를 세는 방법을 의미합니다. 수를 셀 때, 0부터 몇까지 세는지를 의미한다고 생각하시면 됩니다.

우리가 수를 셀 때, 0~9까지 세지요? 이 것을 10진법이라고 부릅니다. 시간에서 분, 초 등을 셀 때 쓰이는 0~59까지 세는 방법을 60진법이라고 합니다. 이와 달리 컴퓨터는 전류가 흐를 때(1)와, 아닐 때(0) 밖에 구분하지 못하기 때문에, 0과 1로써 수를 세는데 이를 2진법이라고 부릅니다.

게임과 메신저, 음악 재생과 같은 것들이 0과 1만으로 된다는 게 말이나 되냐며 못 믿으실 분들도 계실 텐데요, 이 것은 챕터2 비트의 법칙에서 자세히 설명하도록 하겠습니다.

2진법

2진법(Binary)는 0과 1로써 수를 세는 방법입니다. 자리수가 2가 되었을 때 자리 올림을 하여 10으로 표시하는 수 체계죠.

2진수는 표현할 때,

0011(2)

위와 같이 표현 하곤 합니다. 괄호와 그 안에 숫자는 반드시 써야 하는 건 아니고, 혼돈의 여지가 있을 때만 사용 하곤 합니다.

2진수 10진수
0000 0
0001 1
0010 2
0011 3
0100 4
0101 5
0110 6
0111 7
1000 8
1001 9
1010 10

위의 표를 보시면, 대강 어떤지 감이 오실 겁니다. 10진수가 11일 때 2진수로는 몇이 될까요? 네 그렇죠~ 1011이 되는 겁니다. 그런데.. 2진수가 너무 읽기 힘들죠?

8 4 2 1
1 0 0 1 //자릿수가 1일 때마다, 머리 위에 위치한 수만큼 더해줍니다

8에 위치한 2진수가 1이니 8, 4와 2자리에 위치한 수는 0이니 그냥 내버려두고, 1의 자리에 위치한 수가 1이니 1. 그래서 나온 수인 8과 1을 더하면 9가 되는 거죠. 방금 전 방식보단 읽기 쉬워졌죠?

마찬가지로 이진수가 커질 때에도

128 64 32 16   8 4 2 1
0  0  0  0    0 0 0 0

이런 식으로, 수가 하나 증가할 때마다 수가 배로 증가하게 됩니다. 이렇게 하니 2진수 읽는 법은 감이 오죠?

그런데.. 음수를 표현할 땐 어떻게 해야 할까요? -0011

이런 식으로 하면 될 거라고 생각 하신 분 들이 많으실 것 같습니다.

아쉽게도, 컴퓨터 에서 수를 다룰 때는 -부호를 사용할 수 없습니다.

그래서 최상위 비트(MSB: 가장 앞에 있는 비트를 의미)를 부호 비트로 사용하게 되는 것이죠. 비트란 다음 강좌에서 배우게 될 Binary Digit 약자입니다.

최상위 비트가 0이면 양수, 1이면 음수로 표현 하기로 했습니다. 0001은 1, 1001은 -1 이렇게 말이죠.

그런데 이것은 문제가 있습니다. 2진수의 계산이 힘들어진 것이죠.

1001 + 0001 = 1010
(-1)   (1)   (0 이어야 함)

2진수의 덧셈에서 자리 올림수가 발생하면 일반 덧셈에서 자리 올림 수와 마찬가지로 처리해주면 됩니다.

그건 그렇고, 뭔가 이상하죠? 1010이라니…최상위 비트가 1이니 음수인 거 같고, 뒤가 010이니 -2인 것 같은데… 어? 0이 아니네요?

그래서 나온 것이 1의 보수입니다.

1의 보수란, 음수 표현 시에 0을 1로, 1을 영으로 모든 수를 반전 시키는 것이죠.

1의 보수로 표현하자면, 0001은 1, 1110은 -1이 되는 거죠.

자.. 아까 계산이 잘못되었던 -1에서 1을 더해볼까요?

1110 + 0001 = 1111
(-1)   (1)    (0이어야 함)

어? 여전히 뭔가 이상하죠?? 최상위 비트가 1이니 음수인 거 같고.. 111이라면 -7? 왜 또 0이 아니지? 또 문제가 있었습니다. 그래서 2의 보수란 것이 나오게 된 것입니다.

2의 보수란 0을 1로, 1을 0으로 모두 바꿔준 후에 1을 더하는 방법입니다.

0001은 1, 1111은 -1이 되는 것이죠.

그럼 다시.. 계속 잘못 되었던 계산인 -7에서 7을 더해봅시다.

1111 + 0001 = 10000
(-1)   (1)   (0이어야 함)

음.. 이번에도 최상위 비트가 1이군요. 그럼 음순가? 그런데 뒤가 0000이네요? 하지만 이 계산은 맞습니다. 맨 앞에 초과된 1은 무시하기 때문입니다. 그래서 0000 즉 0이 되는 것이죠.

왜 2의 보수가 사용되는지 아셨겠죠?

참고로 1의 보수의 또 다른 문제점은 0이 두 개이기 때문입니다. 1111 1111과, 0000 0000 각각 음수 0 양수 0을 의미합니다.

이에 비해 2의 보수는 0000 0000은 당연히 0이고, 0의 1의 보수인 1111 1111에서 1을 더하면 1 0000 0000이 되고, 이때 초과된 1은 무시하게 되므로 0은 양수 0 하나만 남게 되는 것이죠. 이로써 아까 -1에서 1을 더하는 계산에서의 초과된 1을 무시하는 이유도 함께 이해가 되시죠?

8진법

8진법(Octal)이란 0~7로 수를 세고, 자릿수가 7이 넘어 8이 되었을 때는 자리 올림 하여서, 10으로 표현하는 수 체계입니다.

8진수는 표기할 때,

12(8)

이런 식으로 작은 괄호로 8을 붙여서 표현하곤 하지만, 2진수와 마찬가지로 반드시 표기해줄 필요는 없습니다.

C언어 등의 고급 언어에서 사용시 일반적으로 숫자0을 붙여서 사용하죠.

012

아래 표를 보시면, 2진수, 8진수, 10진수의 관계를 아실 수 있을 겁니다.

2진수 8진수 10진수
0000 0 0
0001 1 1
0010 2 2
0011 3 3
0100 4 4
0101 5 5
0110 6 6
0111 7 7
1000 10 8
1001 11 9
1010 12 10

8진수는 그 자체적인 의미도 중요하지만, 2진수에서의 변환이 매우 편리하다는 장점이 있습니다. 바로 수를 세 개 단위로 묶어서 표현하면 되는 것이죠.

4 2 1
1 1 1 //7입니다

8진수로 바꿀 때는, 4+2+1=7이 되는 거죠.

이런 식으로, 두 자리 수 이상일 때도 마찬가지로,

4 2 1    4 2 1
1 1 0    0 1 1
4+2=6    2+1=3

8진수로 63이 되는 겁니다.

16진법

16진법(Hexadecimal)이란, 수를 0부터 15로 세다가, 16이 되어 자리 올림 시 10으로 표현하는 방법을 말합니다. 그런데…뭔가 조금 이상하죠? 0~15로 수를 센다면, 0~9는 괜찮겠지만, 10부터 15는 자리 올림 된 10~15와 같게 되니까요. 그래서 16진수에서는 0~9는 10진수와 같이 표기하고, 10~15는 A~F로 표현하게 됩니다.

16진수도 8진수 2진수와 마찬가지로,

AF (16)

위와 같이 표기할 수 있습니다.

C언어 등 고급언어에서 16진수 표현할 때 숫자 앞에 0x (숫자 0과 알파벳 x)를 붙여서 사용합니다.

0xAF

아래 표를 보시면 진법에 따른 수 표현 방식을 이해 하실 수 있을 겁니다.

2진수 8진수 10진수 16진수
0000 0 0 0
0001 1 1 1
0010 2 2 2
0011 3 3 3
0100 4 4 4
0101 5 5 5
0110 6 6 6
0111 7 7 7
1000 10 8 8
1001 11 9 9
1010 12 10 A
1000 13 11 B
1001 14 12 C
1010 15 13 D
1010 16 14 E
1010 17 15 F
1010 20 16 10

16진수도 8진수처럼 2진수에서의 변환이 쉽다고 했었죠?

16진수도 2진수를 8진수로 변환하는 것과 비슷합니다. 2진수 4개씩 묶어서 16진수로 변환하면 되는 것이죠.

8 4 2 1
1 1 0 0 //12입니다

8+4=12인데, 12는 알파벳 C로 표현하기로 했으니,

8+4=C로 표현할 수 있는 것이죠.

8 4 2 1    8 4 2 1
1 0 1 0    0 0 1 1
8+2=A      2+1=3

A3으로 4자리씩 묶어서 변환함으로써 2진수를 좀 더 읽기 쉽게 하는 것이죠. 기계어에서 표현하는 수 체계도 16진법이므로 알아두면 여러모로 도움이 되겠죠?

(서평) 레이몬드 첸의 윈도우 개발 282 스토리 - 윈도우의 현재를 말해주는 비하인드 스토리

윈도우 개발 스토리? 저는 매우 궁금했습니다. 맥이나 리눅스에 비해 윈도우가 압도적인 점유율을 갖고 있지만 그만한 인정은 못받고 있지만, 저는 윈도우가 매우 뛰어나고 M$라 불릴만큼 악덕 기업은 아니라고 생각하기 때문입니다. 

그들은 비주얼 스튜디오 만으로도 존경 받을만하죠. (MS만세~)

레이몬드 첸씨의 이름을 달고 나온 책인 만큼 그가 누구인지 매우 궁금했는데, 윈도우 개발에 수석 프로그래머 이셨더군요. 부럽습니다!

이 책은 주로 윈도우를 개발하며 겪은 에피소드와 왜 윈도우가 이렇게 돌아가는 지에 대한 항변(?)을 하는 식으로 이루어져 있습니다.

윈도우는 대부분 사용자 편의에 큰 가치를 두고 있고, 그 대표적인 방침중 하나가 하위 호환이라 할 수 있습니다.

하위 호환을 위해 유지해야 했던 문제 되는 함수들, 잘못된 사용법으로 인해 윈도우가 망가졌던 일, 그런 사용에도 망가지지 않기 위해 했던 예외처리 등 윈도우의 파란만장한 주옥같은 일화들이 많이 있었습니다.

그 중에서도 특히 심시티를 하위 호환하기 위해서 집어넣었던 예외 처리 코드가 정말 인상적이었는데요, 심시티가 그만큼 큰 파급효과를 가졌었다는 점에서 부럽기도 했습니다. (MS가 그 게임 하나만을 위한 코드를 작성해주다니… 쳇… 멋진데?)

WIN16 호환을 위한 수많은 역사와 얽혀있는 코드들에 대해서 설명해주는데, 다른 내용도 매우 많지만 hPrevInstance에 대해 이보다 자세하게 설명해준 책은 아마 없었던 것 같네요. (이 부분은 Windows API 정복을 비롯한 윈도우 프로그래밍 서적들에어느정도 설명이 나오기도 했지만 깊이가 다르다! 깊이가!)

설명 위주의 책이긴 하지만 조각 코드도 꽤 되고, 궁금했던 얘기들로 꼭 집어 설명해주는 것은 수석 프로그래머 였던 그가 아니면 불가능 했을 거란 생각이 드네요.

MS가 윈도우에서 가져간 정책의 밑바탕에는 사용자가 중심이었습니다. 어찌보면 당연한 얘기지만 내가 얼마나 그렇게 해왔나라는 반성이 들어 부끄럽기도 했습니다.

개발을 하다보면 기획자나 그래픽 디자이너가 힘든 방법이지만 내가 편하거나, 코드 상으로 간결한 해결책을 가져다 주는 방법을 선택하고 싶은 욕심이 생길때가 있고, 실제 그런 선택을 할 때가 있습니다.

어찌보면 프로그래머로써 우선시 여기는 유지보수 쉬운 코드, 퍼포먼스 좋은 코드 같은 가치 보다,  중요한 가치가 사용자나 팀웍이 될 수도 있다는 생각이 들기도 했습니다.

물론 이 책을 다 읽고 난 지금은 전보다 사용자나 팀을 위한 노력을 조금 더 기울이게 됐지만, 여전히 저에게 우선 되는 가치는 유지보수 쉬운 코드나 퍼포먼스 좋은 코드지만 말이죠. (….. -_-;; 제가 고집이 좀 쎕니다…쿨럭!)

이 책은 제가 전공서를 읽을때 조차 중요시 여기는 가치인 재미를 주는 책이었습니다. 마냥 윈도우 매뉴얼을 읽고 싶으신 분들은 MSDN을 찾아보세요. 파라미터 하나 하나 자세히 알려줄테니까요.

하지만 조금이라도 윈도우 프로그래밍 하실 여지가 있다면, 아니 윈도우를 조금 더 잘 사용하시려는 일반 사용자라고 하실지라도 윈도우의 기본 철학, 윈도우를 만들었던 과정들에 대해 알고 싶다면 이 책을 반드시 읽어보시기 바랍니다.

(서평) Art of Unix Programming - 프로그래머가 가져야 할 마음 가짐을 알려주는 좋은 책.

제가 프로그래밍을 접한 시기가 97년이고, 윈도우 프로그래밍에 대한 정보를 얻기도 쉽지 않은 시기였습니다. (도서관도 시립 도서관외에는 힘들었고, 집 근처에 도서관이 없던지라 서점에 파는 책들이 전부였죠)

그런 상황에서 유닉스나, 리눅스 프로그래밍은 더 접하기 어려웠고, 그렇다보니 자연스레 윈도우 프로그래머가 되었습니다.

굳이 리눅스를 접해야만 할 이유가 없었고, 윈도우에 만족하고 있었지만, 현대 운영체제의 모태인 유닉스 계열 운영체제를 접해봐야 왜 그렇게 만들어졌는지 알아야만 윈도우 프로그래밍을 더 잘할 수도 있겠고, 유닉스 계열 운영체제가 맘에 든다면 그쪽으로 개발하는것도 괜찮겠다는 생각에 Fedora를 시작으로 리눅스를 사용하게 되었습니다.

서버 프로그래머이다보니 네트웍에 관심을 갖고 있는 것도 한몫 했죠.

책의 전반적인 내용은 프로그래머가 가져야 할 마음 가짐과 왜 유닉스가 개인 사용자가 느끼기에 불편한가 하는 것에 대한 이야기를 하고 있습니다.

유닉스는 프로그래머를 위한 문화이고, 그래서 프로그래머들의 기호를 맞추기 위해 세심한 조작이 가능하게 하였고, 서로 다른 프로그램이 상호 작용 하기 쉬워야 한다는 것이죠.

그러기 위해선 에러가 아닐 때에는 아무런 메시지도 띄우지 말아야 하고, 그런 역사가 과거 연산 속도가 떨어져 메시지 출력이란 작업이 비싼 작업 이었을 때로 부터 이어져 내려왔다는 것도 알 수 있었습니다.

그런 부분들이 일반 사용자가 느끼기에 불친절 할 수 있고, 어렵다는 점에 대해서는 저자도 인정하고 있었습니다만, 유닉스의 가치가 거기에 있는 것이 아니기에 유닉스는 인정 받아야 한다는 의견을 피력하고 있었습니다.

제 생각에도 유닉스는 뛰어난 운영체제이고 인정 받아 마땅하며, 이미 인정 받고 있죠.

하지만, 지나친 유닉스 사랑이 윈도우를 폄하하는 오류를 범하게 하고 말았습니다. 사용자 중심의 윈도우 문화는 폄하되어선 안된다고 봅니다.

오히려 사용자 중심적인 문화는 지향 되어야 하는 것이라고 생각합니다.

에릭 레이몬드씨가 지적한 문제점들이 사실이긴하나, 유닉스의 단점들에 이유가 있었듯이, 윈도우가 그렇게 된 이유들도 다 납득이 갈만한 이유가 있습니다.

유닉스 문화의 문제점을 지적하는 자기 성찰적 면모를 보이기도 했지만, 그렇다고 해서 윈도우의 단점만 지적한것까지 옳은 판단이라고 받아들일 수는 없었습니다.

많은 프로그래머에게 귀감이 될만한 좋은 내용이 넘치는 이 책에 많지 않은 내용이지만 윈도우에 대한 험담으로 그 가치가 조금 떨어졌지만, 그래도 여전히 좋은 책이고, 유닉스 프로그래머들에게는 자부심을, 그리고 유닉스에 대한 이해도를 높여주며, 윈도우 프로그래머들에게는 유닉스 문화에 대한 이해를, 그리고 윈도우 문화에 대한 고찰을 할 수 있는 좋은 책이었다고 생각드는 책이었습니다.

(서평) 패턴 그리고 객체지향적 코딩의 법칙 - 그들의 경험을 쉽게 이해하는 한가지 방법

이 책은 경험이 쌓이면서 알게되는 진리들 (성급한 최적화, 객체지향 설계가 필요한 이유, 중복 제거가 필요한 이유 등등) 을 쉽게 설명해주고 있습니다.

전공이 컴퓨터 공학이었다보니 선후배나 동기들이 프로그래밍을 어떻게 하면 쉽게 배울 수 있느냐고 물어봅니다.

그런 부분에서는 이 책도 해답이 되긴 힘들다고 생각합니다. 이 책은 프로그래밍의 방법을 알려주는 책은 아니니까요.

제 생각에 이 책은 프로그래밍이란 과정은 알아가는데, 좀 더 유지보수하기 좋고, 이해하기 쉬운 코드를 목표로 삼고 있는 프로그래머들이 읽으면 적당한 책이라고 생각합니다.

저도 이 책의 나고수씨와 같이 패턴이름들을 외우고 있지 않습니다.

기껏 외우는거라 봤자 팩토리, 싱글턴 정도였죠. 하지만 사용해왔던 클래스 형식이나 구조들이 거의다 패턴으로 있더군요.

그런걸 보면 패턴은 의사소통의 수단중에 하나고, 코드 구조를 정리하는 수단이라고 볼 수 있죠.

사실 프로그램을 잘 모르는 상태에서 흔히 듣는 얘기가 회사들어가면 금방 알게 된다 하지만 그렇지 않은 경우도 많습니다.

결국은 어떤 것이 왜 좋은지, 왜 나쁜지에 대한 이해가 이뤄져야만 하죠. 주로 그것이 경험을 통해 이뤄지는 것이지만, 그런 상황을 알려주는 이 책도 한가지 방법이 될 수 있다고 봅니다.

저는 예전 경험들을 되돌아보는 느낌으로 읽었지만, 이제 처음 시작하시는 분들에게는 대리 경험으로써 큰 도움이 될꺼라 생각되는 좋은 책이었습니다.

(서평) 네트워크를 훔쳐라 - 그들의 심리를 파악하자

나는 공격하는 자보다는 방어하는 자의 입장이다.

그런데 왜 보안 서적이 아닌 해킹 관련 서적을 보냐고? 보안이란 이미 알려진 취약점을 틀어 막는다고 되는 것이 아니기 때문이다.

해킹이란 단순히 뛰어난 컴퓨터 지식을 기반으로한 공격 기술만을 말하는 것이 아니다.

책의 내용중 해커들이 파고 들 수 있는 시스템 취약점이 많다는 사실은 새삼 놀랠만한 내용은 아니었다.

뭐 당연한 것이겠지.

프로그래머가 실수를 했을 수도 있고, 악용될 여지의 취약점을 모두 고려한다는 건 쉬운 일이 아니기 때문이.

이 책에서 설명한 공격 코드가 시스템의 어떤 취약점을 파고 들었고, 어떠한 생각을 가지고 다른 빈틈을 찾아나가는지에 대해 이해하는 것은 크나큰 소득이었다.

막연히 이렇게 해야 한다 라고 알고 있는 것보다, 어떤 취약점이 무엇 때문에 문제가 됐기에 막아야 한다는 것을 아는 것이 중요하다.

또한 기술적인 부분보다 심리적인 부분의 취약점이 더 클 수 있다는 내용들을 보며, 나의 보안의식에 대해 다시 한번 돌아보게 되었다. 나 역시 비밀번호를 다양하게 사용하지 않고 있으며, 공유 폴더에 중요한 자료를 꽤나 긴 시간 동안 넣어둔 적이 있다. 물론 그 공유 폴더가 사내에만 공유되는 것이지만, 사내 네트웍이 뚫렸다면?? 끔찍한 일이다.

소설과 같은 형식이다보니 기술적인 디테일은 부족했다. 하지만 나에겐 기술적인 디테일을 다룬 서적들 이상을 얻을 수 있었던 좋은 서적이었다.