앞장에서 우리는 재미있는 사실을 하나 발견하였습니다.

 

대문자 'A'와 숫자 65는 컴퓨터에서 같은것으로 인식한다는 것을요.

 

간단하게 설명을 드렸던

"컴퓨터는 모든 데이터를 숫자로 기억한다"를 기억하시는 지요?

 

대부분의 고급언어에서는 필요가 없는 내용일지도 모르겠으나

C언어를 공부했다면, 그리고 C언어를 공부하고 있다면

위 사실은 매우 중요한 사실입니다.

 

하나의 컴퓨터 프로그래밍 언어가

그 프로그램이 작동하는 컴퓨터와 어떤 관계를 가지고 있으며

컴퓨터(하드웨어)는 어떤 식으로 데이터를 처리하고 보관하는지는

사실 C언어에서 매우 중요한 사실입니다.

 

이쯔음에서 저는 아주 많은 고민을 하였습니다.

 

초보자 분들에게 C 언어를 설명하면서 자료형이란것에 대해서 얼마나 상세하게 가르쳐 드려야 할까를 놓고 심각하게 고민해 봤습니다.

 

다양한 자료형에 대한 예제를 통하여 자료형을 다루는것만 능숙하게 해드릴것인가

 

아니면 자료형에 대한 근본적인 이해를 시켜드릴것인가를요.

 

모든 것을 100% 완벽하게 가르쳐 드리면 얼마나 좋겠습니까만은 그러기에는 자료형이라는 것이 컴퓨터에 대한 많은 기본적인 이해를 필요로 하기에 제가 본 오래된 C 언어 책에서는 지금부터 설명드릴 진법에 대한 설명은 거의 생략되거나 축소 되어 있었고 거의 모든 책에서 앞서 제가 설명한 단순히 비트나 바이트 개념만을 언급하여 컴퓨터에서 얼마나 큰 숫자를 나타낼수 있는가만을 이야기 하였습니다.

 

C언어가 배우기 어렵다고 이야기 하는 첫 번째 이유가 바로 자료형의 이해 이것이 아닐까 생각을 하면서 감히 여러분들에게 어렵지만 앞으로 만나게 될 모든 문제를 인간의 방식이 아닌 컴퓨터적인 사고로 문제를 풀수 있는 핵심 지식이 될꺼라 믿으면 감히 진법부터 과감하게 설명을 드리겠습니다.

 

필자는 이렇게 말하고 싶습니다.

 

"진법을 모르는 컴퓨터 프로그래머는 컴퓨터 프로그래머가 아니라" 라고 까지 말하고 싶습니다.

 

그 이유는 컴퓨터가 어떤 체계와 약속으로 바탕으로 작동하며 어떤식으로 작동하지는 알지 못하는 프로그래머라면 단순히 프로그램 코드를 작성하는 사람이지 가장 효율적이고 가장 최적화된 방식으로 프로그램을 하지 못하기 때문입니다.

 

그러나 본 진법부분의 내용을 읽어도 이해가 안되시는 분들을 위해서 동영상 강의를 준비하여 두겠습니다.

(추후 만들어 두겠습니다. 예전 자료가 있었는데 소실 되었네요. ㅠ.ㅠ)

 

 

자, 준비 되셨나요?

 

그럼 컴퓨터는 어떻게, 어떤식으로 잘동하는지 진법의 세계로 한번 빠져 보겠습니다.

 

다시 한번 강조하지만

실제로 컴퓨터는 모든 데이터를 숫자 형태로만 저장한다는 것을 말씀 드렸었습니다.

 

쉽게 바꾸어 말하면 여러분들이 가지신 어떠한 저장장치(RAM, SSD, HDD)라도 그곳에는 숫자만 기록 되어있지 문자 형태의 데이터가 기록되어 있지 않다는 뜻입니다.

 

좀더 정확하게 이야기 하면 모든 데이터를 2진수 형태의 숫자 저장하고 2진수 형태로 처리를 합니다.

 

2진수는 0 또는1을 사용하는 숫자 체계인데요.

2진수가 뭔지는 잠시후에 설명 드리겠습니다.

 

그런데말입니다.

 

이제껏 우리가 보아 왔던 에제들은

10진수 형태의 정수, 실수 데이터를 입력하고 거기다가 문자 데이터 혹은 문자열 데이터까지 입력하고 출력하는 법을 배웠습니다. 그렇다면 컴퓨터는 왜 2진수를 사용하고 어떻게 2진수를 이용해서 10진 데이터와 문자 데이터를 처리하는 걸까요?

 

그 궁금증을 하나씩 풀어보겠습니다.

 

C언어 입문자 분들에게는 상당히 어렵고 난해한 내용이 겠지만

 

이것이 C 언어가 아직까지 교육용 언어로 사랑받고

배우기 힘들지만 배워두면 모든 프로그래밍 언어의 기본이 된다는 것을 느낄수 있게 하는 장이기도 합니다.

 

자 본격적으로 이야기 해보도록 하겠습니다.

 

우선 우리는 컴퓨터는 무엇을 먹고 살까요? 라는 질문부터 출발을 해보겠습니다.

 

컴퓨터는 전기를 먹고 사는 기계입니다.

 

전기를 먹고 산다는 것은 크게 두가지 상태를 컴퓨터가 인식할수 있다는 뜻이기도 합니다.

 

하나는 전기가 흐르는 상태, 하나는 전기가 흐르지 않는 상태로 나눌수 있습니다.

 

컴퓨터에는 보통 전기가 흐르는 상태를 5V(볼트)로 가정하고 전기가 흐르지 않는 상태를 0V(볼트)로 가정합니다.

(일반적으로 CPU에서 사용하는 전압은 1.2V 정도이고 점점 낮아지는 추세입니다.)

 

일반적으로 이 전기적 상태 혹은 전압을 숫자로 표현하자면 전기가 흐르는 상태를 1이라 생각하고 전기가 흐르지 않는 상태를 0이라 생각할수 있습니다.

 

전기적인 상태를 숫자로 생각을 하지는 거지요.

 

전기가 흐른다 : 5V = 숫자 1

전기가 흐르지 않는다 : 0V = 숫자 0

 

결론적으로 전기적인 특성을 이용하게 될 경우

컴퓨터는 0과 1을 구분할수 있는 논리 체계를가질수 있다는 뜻입니다.

 

좀더 정확히 이야기 하자면 0과 1의 상태를 약속한것이라고 할수 있겠네요.

 

 

그럼 다시 본론으로 돌아와서

 

숫자 0과 1을 사용해서 모든 숫자를 나타내는 진법을 우리는 2진법이라고 합니다.

 

왜 2진법이라고 하는지부터 한번더 살펴 보기로 하겠습니다.

 

 

여러분들이 흔히 사용하는 수를 10진수라고 하며 이러한 수 논리 체계를 10진법 이라고 합니다.

 

저는 진법의 정의를 이렇게 내립니다.

 

진법이란 숫자를 나타내는 기호의 개수라고 말하고 싶습니다.

 

우리가 사용하는 10진법은 기호 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 이렇게 총 10개의 기호를 사용합니다. 보시는 것과 같이 10진법에 10이라는 기호는 없습니다. 10은 기호 1과 기호 0이 합쳐져서 만들어진 것이지 하나의 기호는 아닙니다.

 

정리하자면, 진법에서 말하는 기호의 갯수는 단일 기호를 말하는것입니다.

 

그래서 10진법에서 필요로 하는 기호는 총 10개이며

 

8진법에서 사용하는 기호는 총 8개 즉 0, 1, 2, 3, 4, 5, 6, 7 이렇게 8개이며

 

2진법에서 사용하는 기호는 0, 1, 이렇게 2개의 기호를 사용합니다.

 

 

저는 우스개 소리로 붕어빵에는 붕어가 없고 10진법에는 10이 없다라고 말합니다. 

 

그럼에도 불구하고 우리는

 

10진법에는 없다는 10, 11, 12, 13 심지어 150, 2543이라는 큰 숫자들도 표현을 하지요.

 

참 묘한 이야기 이지요.

 

자 그럼 우리가 아주 자연스럽게 사용하는 10진법에서 왜 9 + 1 = 10 이라고 표현 하는지

그리고 10이라는 숫자 표현은 어떤 방식으로 만들어지지 한번 살펴 보도록 하겠습니다.

 

모든 진법에서는 이전 기호와 다음 기호 사이의 크기는 1차이가 나는 것으로 간주 합니다.

 

 

기호 0과 1의 차이는 1이라는 뜻이며

기호 1과 2의 차이 또한 1이며

기호 2와 3의 차이 또한 1이라는 것입니다.

 

우리가 흔히 사용하는 10진법에서 1 + 1 이라는 뜻은 1 다음 기호가 무엇이냐고 묻는 뜻이며 정답은 2가 됩니다.

 

왜 그럴까요?

10진법에서 사용하는 기호를 순서대로 나열해 보면

 

0, 1, 2, 3, 4, 5, 6, 7, 8, 9 인데

 

1 + 1 은 1 다음 기호를 묻는것이라고 하였습니다.

 

2 + 1은 2 다음 기호를 묻는 것이라고 하였습니다

 

위 기호의 나열 순서를 잘 보시면 금방 그 이유를 아실수 있겠지요?

 

필자가 친절하게 다시 설명하자면

 

2 + 1은 2 다음 기호를 묻는 것인데

 

0, 1, 2, 3, 4, 5, 6, 7, 8, 9 에서 보시는 바와 같이

2 다음 기호는 3입니다.

 

그림으로 도식화 해보자면

 

 

그래서 10진법에서 2 + 1 은 3이라는 연산이 성립하게 됩니다.

 

자 그럼 4 다음 기호는 무엇일까요? 당연히 5라고 힘차게 대답하셨을꺼라 믿습니다.

 

4  + 1 = 5이 라는 산수 계산이 아닌

 

10진법에서 4 다음 기호는 5 이다 라고 생각하셨을꺼라고도 믿습니다.

 

 

자 여기서 우리는 10진법의 기호를 다시 한번 적어 보겠습니다.

 

0, 1, 2, 3, 4, 5, 6, 7, 8, 9

 

이렇게 총 10개의 기호가 있습니다.

 

질문을 한번 드려볼께요.

 

9 다음 기호는 무엇인가요?

 

 

 

위 그림에서 보시는 바와 같이

9 다음에는 기호가 없습니다. 그렇쵸?

 

그럼 어떻게 해서 10 이라고 적는 규칙이 만들어 진것일까요?

 

숫자 앞에 0은 무의 하므로 편의상 9를 우리는 09라고 표현하기로 하겠습니다.

 

9다음 기호를 묻는다는 것은

 

   09

   +1

 -----

 

위와 같은 질문입니다.

 

9+1은 9 다음 기호를 묻는것인데 9 다음 기호가 없으므로 맨 처음 기호인 0으로 되돌아 가고

 

 

 

앞자리에 1을 올려(올림수) 줍니다.

 

 

 

그럼

 

  09    <--올림수 1이 발생합니다.

  +1

----

   0  <-- 9 다음 기호가 없으므로 0으로 되돌아감

 

위와 같은 상태가 되며 앞에 09라고 표기된 앞의 0에 1을 더하는 것만 남았습니다.

 

 

0+1(올림수)은 1이므로

 

  09   <--올림수 1이 발생했었죠?

  +1

----

  10

 

 위와 같이 10이라는 답을 얻을수 있습니다.

 

아주 간단한 이야기를 어렵게 적은 듯 하지요?

 

하지만 이러한 논리가 없다면 여러분들은 8진수 연산이나 2진수 연산에서 문제가 발생할수 있으며 10진법이 아닌 다른 진법에서 10(일공) 이 숫자 십이라고 생각하는 오류를 범하기 쉬우며 10 이라는 기호의 의미는 10진수에서는 십이라고 부를수 있지만 8진수에서 10이은 여덟 개를 의미하다는 사실을 알지 못하게 됩니다.

 

자 그럼 8진수에서 10은 왜 8개를 뜻하게 되는지 위와 같은 식으로 다시 한번 분석해 보겠습니다.

 

8진수에서 사용할수 있는 기호는 총 8개로

0, 1, 2, 3, 4, 5, 6, 7입니다. 붕어빵에 붕어가 없듯이 8진수에는 8이 없습니다.

 

자 그럼 7 다음 기호를 물어 볼까요? 다음 기호를 묻는다는 것은 더하기 1을 한다는 의미라고 한 것 기억나시지요?

 

  07

  +1

-----

위와같은 질문으로 변환할수 있겠지요?

 

 

7다음 기호가 없으므로 8진수 기호 맨 앞으로 되돌아가서

 

 

 

0이라는 기호를 적어주고 올림수 1이 발생하게 되므로

 

  07 <--올림수 1 발생

  +1

-----

   0 

 

위와 같이 올림수가 발생한다는 사실을 알수 있습니다.

 

07에서 앞자리 0과 올림수 1을 더하면 1이므로 답은

 

  07   <--올림수 1이 발생했었죠?

  +1

-----

  10

 

위와 같이 10이됩니다.

 

앞서 말씀 드렸다 시피 이숫자는 절대로 십이라고 읽으시면 안됩니다. 8진수에는 팔도 없는데 십이라는 숫자가 있을 리가 없겠지요. 읽으실때는 팔진수 일 공 이라고 읽으시면 됩니다.

 

자 그럼 8진수 10 + 1은 얼마일까요?

 

다시 산수 계산식으로 적어 보면

 

   10

   +1

  --- 

 

위와같은 질문이 됩니다.

 

뒷자리부터 다시 연산해 보면 0 다음 기호를 물으므로 8진수에서 0다음 기호는 1이며 올림수는 발생하지 않습니다.

따라서

 

   10 <---올림수 발생하지 않음

   +1

  --- 

    1

위와 같이 연산되며 올림수가 발생하지 않았으므로 앞의 1을 그냥 내려 주면 됩니다.

 

   10 <---올림수 발생하지 않음

   +1

  --- 

   11

 

결론은 위와 같이 11이 정답이 됩니다.

 

자 그럼 하나만 더해보도록 하겠습니다.

 

8진수 17 +1 은 답이 무엇일까요?

8진수에서 7다음 기호는 없으므로 맨 처음 기호로 되돌아 가서 0을 적은다음 올림수 1이 발생합니다. 올림수 1은 17의 앞자리 1에 더해지므로 앞자리는 2가 되겠지요

 

  17 <--올림수 1 발생

  +1

----

  20

 

결론은 8진수 20이 답이 됩니다. 이제 조금 8진법에 대해서 이해를 하셨나요?

 

그럼 이제 8진수를 0부터 순서대로 한번 적어 보도록 하겠습니다. 즉 1씩 더해서 적어 보도록 하겠습니다. 여러분들이 생각하시는 답과 책에 표기된 답이 맞는지 비교하면서 8진법에 익숙해 지시기 바랍니다.

 

0, 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 15, 16, 17, 20, 21, 22, 23, 24, 25, 26, 27, 30, 31 ........75, 76, 77, 100, 101, 102, 103, 104, 105, 106, 107, 110, 111, 112, 113 위와같은 형태로 쭈~~욱 적을수 있습니다. 실수하기 쉬우면서 중요한 부분은 진하게 표시하여 두었습니다. 앞서 설명한 방식대로 차근 차근 다시 더하기 해보시면 될 듯 합니다.

 

자 그럼 우리가 컴퓨터를 사용할 때 실제로 사용하게될 2진법에 대해서 한번 생각해 보도록 하겠습니다. 모든 진법은 연산 규칙이 동일하다는점 잊지 마시고 차근 차근 한번 살펴 보도록 하겠습니다.

 

별로 적을 것도 없지만 우선 2진수 기호를 순서대로 한번 적어 보겠습니다.

 

0, 1 달랑 두 개의 기호가 있습니다.

 

2진번은 0과 1 기호 2개만을 사용하는 진법으로 0과 1이 반복적으로 나타나므로 자칫 실수 하기 쉬운 부분입니다. 편의상 2진수 4자리를 기준으로 한번 설명 드려보겠습니다.

 

0000은 0과 같다는 정도는 아실수 있겠지요? 숫자에서 앞의 0은 아무런 의미가 없으니깐요.

 

자 그럼 한번 살펴 보도록 하겠습니다.

 

0000

+001

-----

 

위 내용은 0 다음 기호를 물은 것이므로 0다음 기호는 1이며 올림수도 발생하지 않으므로 

 

0000

+001

-----

0001

 

위와같은 계산할수 있습니다.

 

그럼 

 

0001

+001

------

 

위 내용은 1다음 기호를 묻는 것으로 1다음 기호는 2진법에는 없으므로 맨 처음 기호인 0으로 되돌아 가고 앞자리에 1을 올려 줍니다.

 

 

0001 <---올림수 1발생

+001

------

0000

 

올림수는 0001에서 왼쪽 3번째 0에 더해지므로 0다음 기호는 1이므로 1이 됩니다.

 

0001 <---올림수 1발생

+001

------

0010

 

위와 같이 계산이 됩니다. 자릿수를 맞추기 위해서 앞에 0을 2개 추가하면 정답은 0010이 됩니다.

 

그럼 0010 + 1은 답이 무엇일까요? 오른쪽 끝자리 0에 1을 더하는 것으로 0다음 기호는 1이므로 끝자리는 1이되며 올림수는 발생하지 않습니다.

 

0010 <---올림수 발생하지 않음

+001

------

0001

 

위와 같이 계산되며 올림수가 없으므로 왼쪽에서 세 번째 1은 그냥 내려주면 11이 답이 됩니다. 자릿수를 맞추기 위해서 앞에 0을 2개 붙여주면 0011이 답이 됩니다.

 

그럼 16진수는 무엇일까요? 숫자를 나타내는 기호의 개수가 16개인 것을 16진수라고 합니다.

 

일반적으로 사용하는 기호인 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 이렇게 총 10개의 기호와 A, B, C, D, E, F 알파벳 6개를 이용하여 총 16개의 기호를 사용하는 방식으로 기호 A는 열 개, B는 11개, C는 12개, D는 13개, E는 14개, F는 15개의 크기를 나타냅니다.

ACBD와 같은 알파벳을 사용하는 이유는.. 특별한 이유는 없고 열개, 열한개, 열두개를 표현할만한 특별한 기호가 없기 때문입니다.

 

보기 편하게 다시 한번 표기하자면 A(10), B(11), C(12), D(13), E(14), F(15) 와 같은 형태로 표기할수 있습니다. 16진법에 역시나 16은 없지요?

 

자 그럼 16진법의 기호를 순서대로 나열해 보겠습니다.

 

0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F 이렇게 총 16개의 기호가 있습니다.

 

간단한 연산을 통해서 보자면

 

16진수에서는 9+1은 9다음 기호를 묻는 것으로 9다음 기호가 없는 것이 아니라 엄연히 9다음 기호는 A가 있으므로 9+1=A가 답이 됩니다.

 

 

 

같은 방식으로 A+1은 A다음 기호를 묻는 것으로 A 다음 기호는 B가 있으므로 A+1=B가 답이 됩니다. 이해되셨나요?

 

한번더 해볼까요? E+1=F라는 사실은 금방 아실수 있을 껍니다.

 

자 그럼 F+1은 무엇일까요? 편리한 연산을 위해서 문제를 앞에 0을 붙여서 0F+1이라고 생각해보 무방합니다.

 

  0F

  +1

----

 위 문제는 F다음 기호를 묻는 것으로 16진수에서 F 다음 기호는 없으므로 맨 처음 기호인 0으로 되돌아 가고 앞자리에 1을 올려 줍니다.

 

 

  0F <--올림수 1발생

  +1

----

   0

 

0F에서 앞자리 0에 올림수 1을 더해주면 1이되므로 정답은 10이 답이 됩니다. 다시한번 말씀 드리지만 16진 10은 십이라고 읽으시면 안되고 8진수와 같은 방식으로 16진수 일 공 이라고 읽어주셔야 합니다.

 

그럼 16진수 연산을 쭈욱 한번 하면서 어려울만한 부분만 설명 드리도록 하겠습니다.

10 + 1 = 11

11 + 1 = 12

.

.

.

19 + 1 = 1A  <--- 9다음 기호는 A가 있습니다.

1A + 1 = 1B  <--- A 다음 기호는 B입니다.

.

.

.

1F + 1 = 20   <--- F 다음 기호가 없으므로 처음 기호인 0으로 되돌아간뒤 앞자리 올림수 1이 발생하므로 1F의 앞자리 1과 올림수 1을 더하면 2가 됩니다.

20 + 1 = 21

.

.

.

.

29 + 1 = 2A   <---- 9 다음 기호는 A가 있습니다.

2A + 1 = 2B

.

.

.

2F + 1 = 30  <--- F 다음 기호가 없으므로 처음 기호인 0으로 되돌아간뒤 앞자리 올림수 1이 발생하므로 2F의 앞자리 2와 올림수 1을 더하면 3이 됩니다.

.

.

.

.

99 + 1 = 9A  <----  9(뒷자리) 다음 기호는 A가 있습니다. 앞자리는 올림수가 발생하지 않았으므로 아무런 변화가 없습니다.

.

.

 

9F + 1 = A0   <--- F 다음 기호가 없으므로 맨 처음 기호로 0으로 되돌아 간뒤 올림수 1이 발생합니다. 앞자리 9와 올림수 1을 더하면 9다음 기호를 묻는 것으로 9 다음 기호는 A입니다.

 

대략 이정도까지 무난하게 따라 오셨다면 진법에 대해서는 어느정도 이해를 하셨을 꺼라고 생각합니다.

 

자 그럼 진법을 배웠으니 각 진법들의 관계를 한번 이해 해 보도록 하겠습니다.

숫자와 숫자 사이의 띄어쓰기는 이해를 돕기 위하여 띄어쓰기 해뒀습니다.

 

 

10진법

2진법

8진법

16진법

00

00 0000

00

00

01

00 0001

01

01

02

00 0010

02

02

03

00 0011

03

03

04

00 0100

04

04

05

00 0101

05

05

06

00 0110

06

06

07

00 0111

07

07

08

00 1000

10

08

09

00 1001

11

09

10

00 1010

12

0A

11

00 1011

13

0B

12

00 1100

14

0C

13

00 1101

15

0D

14

00 1110

16

0E

15

00 1111

17

0F

16

01 0000

20

10

17

01 0001

21

11

18

01 0010

22

12

19

01 0011

23

13

20

01 0100

24

14

21

01 0101

25

15

22

01 0110

26

16

23

01 0111

27

17

24

01 1000

30

18

25

01 1001

31

19

26

01 1010

32

1A

27

01 1011

33

1B

28

01 1100

34

1C

29

01 1101

35

1D

30

01 1110

36

1E

31

01 1111

37

1F

32

10 0000

40

20

33

10 0001

41

21

 

 

 

위 표를 보는 방법은 간단합니다. 같은 줄에 적혀 있는 각각의 진법은 그 숫자의 크기가 동일 하다는 뜻입니다.

 

단지 표현한 진법이 다를뿐이라는 것지 크기는 같다는 뜻입니다.

 

가령 10진법 03과 같은 크기를 가지는 2진법 숫자는 00 0011, 8진법 숫자는 03, 16진법 숫자는 03입니다.

 

10진법 24와 같은 크기를 가지는 2진법 숫자는 01 1000, 8진법 숫자는 30, 16진법 숫자는 18입니다. 대략 표 보시는 법을 이해 하셨는지요

 

다르게 이야기 하면 2진법 01 1000은 10진수 24로 변환이 가능하고 16진수 18은 8진수 30으로도 변환이 가능하다는 것입니다. 같은줄에 적혀 있는 숫자는 모두 같은 크기를 나타내며 진법은 서로 상호 변환하였을 답이 된다는 뜻이기도 합니다.

 

우리는 이제껏 각 진법의 숫자를 +1을 이용하여 순서대로 크기를 증가 시키면서 적는 법을 배웠습니다.

(직접 +1 방식으로 계속 다음 기호를 찾는 연습을 충분히 하실수록 책 내용의 이해가 빨라 집니다.)

 

그렇다면 우리는 이제 진법의 상호 변환을 이해 하여야 합니다.

 

중.고등학교에서 배운 진법변환을 기억하시는지요?

 

원칙은 그렇게 변환하는 것이 맞을수 있느나.

우리가 컴퓨터를 배우면서 일반적으로 사용할 진법인 2진, 8진, 16진을 잘 보시면 2의 누승 형태의 진법임을 알수 있습니다.

 

너무나 당연한 것이 컴퓨터는 2진수를 사용하고 사람은 10진법을 사용하므로 실제로는 2진과 10진법간의 변환만 이해하면 되지만 2진법의 단점중 하나가 컴퓨터 연산에는 효율적이겠으나 크기가 증가할수록 사람이 숫자를 읽을 때 자리수가 너무 많아서 불편하다는 것입니다.

 

앞서 보신 2진수 01 1000만 하더라도 여섯자리 숫자인데 이를 16진으로 바꾸어 보면 18로 간단하게 두자리로 만들어 낼수 있습니다. 그럼 왜 하필 8진과 16진이냐? 앞서 2의 누승 형태라는 정답을 말씀 드렸다 시피 2진, 8진, 16진은 어려운 수학을 동원하지 않더라도 상호 변환이 아주 간단하다는 점입니다.

 

10진수를 기준으로 한번 예을 들어 보겠습니다.수학에서 말하는 정석 형태서 조금 벗어나지만 필자는 이렇게 생각하고 이렇게 이해하고 이렇게 가르치고 있습니다.

 

가령 10진수

 

5374 라는 숫자는 5와 3과 7과 4라는 숫자가 합해진 형태로

 

5는 1000의 자리

3은  100의 자리

7은   10의 자리

4는    1의 자리

 

여기서 우리는 5가 있는 곳의 자리값은 1000, 3이 있는 곳의 자리값은 100, 7이 있는 곳의 자리값은 10, 4가 있는 곳의 자리값은 1이라고 할수 있습니다. 이는 10진수 자리값에 해당하는 것입니다.

 

그렇다면 5에 그 자리값을 적용해보면 5000이 될것이고 3에 그 자리값을 적용해보면 300이 될것이고 7에 그 자리값을 적용하면 70이 될것이며 4에 그 자리값을 적용하면 4가 됩니다.

 

순서대로 적자면

 

5000

300

 70

  4

 

위와같은 형태로 변환할수 있습니다.

 

위 숫자들의 합이 5374라는 것입니다.

 

이미 알고 계시겠지만 

1000이란 10의 3승

 100이란 10의 2승을 말하며

  10이란 10의 1승을 말하며

   1이란 10의 0승을 말합니다.

 

10진수 자리값을 잘보시면 10의 누승 형태로 나타난다는 것을 이해 하셨는지요?

 

그럼 이것을 2진수에 대해서 적용해 보겠습니다.

 

 

2진수

1 0111 이라는 숫자는

 

1 0000

0 0000

0 0100

0 0010

000

 

위와 같은 숫자들이 합해진 형태라는 것을 알수 있습니다.

 

자 그럼 자리값들을 표시해 볼까요?

 

1 0000   <-- 2의 4승 자리, 10진수 16에 해당합니다.

0 0000   <-- 2의 3승 자리, 10진수  8에 해당합니다.(어차피 0이라 의미는 없지만)

0100   <-- 2의 2승 자리, 10진수  4에 해당합니다.

0010   <-- 2의 1승 자리, 10진수  2에 해당합니다.

0001   <-- 2의 0승 자리, 10진수  1에 해당합니다.

 

그럼 한번 생각해 보겠습니다. 1 0111 이라는 2진수를 10진수로 변환하기 위해서는 수학에 1이라고 표기된 부분들만 자리값을 합하면 되는 것입니다.

 

이해를 돕기 위해 표를 이용해서 설명을 해보도록 하겠습니다.

 

일반적으로 8자리 기준을 많이 사용하니 이곳에서도 8자리 기준으로 설명을 드리도록 하겠습니다.

 

 

자리값

2의 7

2의 6

2의 5

2의 4

2의 3

2의 2

2의 1

2의 0

128

64

32

16

8

4

2

1

2진수

0

1

0

1

1

1

0

1

 

 

위와 같은 2진수 0101 1101 이라는 숫자를 10진수로 변환하여 그 크기를 알고 싶을 때는 2진수 1에 해당하는 자리만 자리값을 더해주면 됩니다.

 

64 + 16 + 8 + 4 + 1 = 93 임을 간단하게 알수 있습니다.

 

수학시간에 배운 지식을 활용하자면

(0×2의 7승) + (1×2의 6승) + (0×2의 5승) + (1×2의 4승) + (1×2의 3승) + (1×2의 2승) + (0×2의 1승) + (1×2의 0승) 이 됩니다. 우리는 진법변환이 워낙 많이 필요하게 될 것이므로 이 2의 누승값을 암기 형태로 외워두면서 사용할것입니다. 그래서 오른쪽에서부터 순서대로 외우지자면 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 정도까지는 암기해 두시기를 권장 드립니다.

 

자 그럼 조금전 표를 한번더 가져 와 보겠습니다.

 

자리값

2의 7

2의 6

2의 5

2의 4

2의 3

2의 2

2의 1

2의 0

128

64

32

16

8

4

2

1

2진수

1

1

1

1

1

1

1

1

 

 

이진수 1111 1111 은 과연 10진수로 얼마일까요?

 

128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 = 255 임을 금방알수 있습니다.

 

그럼 여기서 한번 제가 독자님들께 궁금한점은 정말로 저 숫자를 책을 보면서 싸~~악 다 더해보니 255가 나오신것인지요?

 

그냥 책쓴사람이 계산한거니깐 안틀리거겠지 하신건가요?

 

네, 물론 제가 암산을 한것이지만 실제로 저값들을 모두 더한 것은 아닙니다.

 

여기서 우리는 재미있는 사실 하나를 알수 있습니다.

 

지금 우리가 알고자 하는 숫자는 1111 1111 이렇게 1이 여덟 개인 2진수의 10진수 변환 값을 알고자 하였으며 이는 255라고 하였습니다.

 

그럼 문제를 바꿔 보겠습니다.

 

1 0000 0000

 

위와같은 9자리 2진수는 10진수로 얼마일까요?

 

1 이 딱 한곳에만 표기 되어 있는 형태입니다.

 

위 표를 응용하면 128 다음 자리값은 128 * 2 이므로  자리값이 256 임을 알수 있습니다.

 

너무나 쉽지요?

 

자 그럼 이런걸 한번 생각해 보죠

 

1 0000 0000

0 1111 1111

 

위 2진수는 얼마 차이가 나는 숫자일까요? 정답부터 말씀 드리면 1차이 나는 숫자입니다.

 

 

 

다시 예문을 드려 볼께요

 

0 1111 1111

0 +000001

 ------------------

1 0000 0000 

 

위와같이 계산이 되는 것이므로 위 두 숫자는 1차이가 나는 것이 맞다는 뜻입니다.

 

자 그럼 다시 본론으로 돌아와서

 

1 0000 0000 은 10진수로 256이므로

0 1111 1111 은 10진수로 256 - 1 = 255임을 알수 있습니다.

 

그럼 더 나아가서

 

1111 1111 은 10진수로 255임을 알았으므로

1011 1111 은 10진수로 255 - 64 = 191 임을 알수 있습니다.

 

위 두숫자는 다 똑같은데 아래 숫자는 0이라고 표기된 부분의 자리값인 64만큼 모자라기 때문에 255 - 64를 한것입니다. 이때 주의하실점음 256 - 64가 아닌 255 - 64라는 점만 주의 하시면 됩니다.

 

위와같이 뺄샘 연산을 하는 것이 더 쉬운 경우는 1의 개수가 아주 많고 0의 개수가 1~2개 정도일때는 더하기를 많이 하기 보다는 뺌샘을 이용하는 것이 더 편리합니다.

 

사실 위 방법을 설명하는 책들은 잘 없는데 굳이 설명하는 이유는

진법이라는 것의 자리값에 대한 명확한 이해를 돕기 위함이며

실전에서 좀더 빠르고 정확한 계산을 통하여 오류를 줄이시는데 도움이 되고자 함입니다.

 

대략 이정도에서 진법은 마무리 지으면서(2진수를 8진수, 16진수로 빠르게 상호변환 하는 것은 추후 설명 하겠습니다.)

 

이제 컴퓨터로 돌아가서 기억장소의 크기에 대한 이야기

즉 비트와 바이트에 대해서 한번 이야기 해보겠습니다.

왜 진법을 배웠으며 2진법 연산을 배웠는지도 확실하게 이해 하시게 될껍니다.

 

컴퓨터에서 가장 작은 정보를 저장하는 단위를 비트라고 이야기 합니다. 컴퓨터가 2진법을 사용하므로 0 또는 1만 기억할수 있는 장치가 필요했고 0 또는 1만 기억할수 있는 1자리 기억장치를 비트라고 합니다.(그래서 2진법을 배운겁니다.)

 

거꾸로 이야기 하면 1비트라는 공간에는 0 또는 1중 하나의 숫자만 기억할수 있다는 뜻입니다.

 

 

그럼 2비트라는 공간은 0 또는 1을 기억할수 있는 공간이 2개라는 뜻이 되겠지요

 

 

그럼 8비트는 0 또는 1을 기억할수 있는 공간이 8개 라는 뜻이며 다르게 풀어서 이야기 하면 1비트 짜리 기억공간이 8개 붙여져 있다는 뜻입니다.

 

 

2진수 한자리는   0 또는 1의 기호를 사용합니다.

1비트 기억장치는 0 또는 1의 숫자를 기억합니다.

 

2진수와 비트는 개념적으로 비슷하거나 똑같다고 느껴지시죠?

 

이제 완전하게 이해 하셨나요?

 

컴퓨터에서 비트라는 공간에 왜 0과 1만 기록이 가능하면 되는지

 

아니 거꾸로 이야기 하면 왜 컴퓨터에서 가장 작은 기억장치 비트를 정의하고 만들 때 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 라는 기호 10 개 중에 한 개를 기억할수 있는 10진 기억장치를 만들지 않고 0 또는 1 두가지 상태중 한가지만 기억할수 있는 기억장치를 만든것인지를요.

 

어찌보면 너무나 당연한 이야기일것입니다. 앞서 컴퓨터는 전기를 먹고 산다고 말씀들 드렸고 전기는 흐르는 상태와 흐르지 않는 두가지 상태 즉 0과 1상태만 존재하므로 컴퓨터는 2진법을 사용할 수밖에 없다고 말씀들 드렸었죠.

 

이 모든 것이 컴퓨터라는 것이 전기를 이용하는 장치이므로 10진 체계보다는 2진 체계가 논리적으로 더효율적이기 때문이라는 것입니다.

 

그래서 컴퓨터의 최소 기억단위인 1비트는 2진수 1자리에 대응하며 2진수 8자리는 8비트에 해당합니다.

 

자 그럼 질문을 한번 드려 보게습니다.

 

8비트로 나타낼수 있는 가장 작은 숫자와 가장 큰 숫자는 10진수로 얼마일까요?

 

이를 다른말로 표현하면

 

2진수 8자리로 나타낼수 있는 가장 작은 크기와 가장 큰 크기는 10진수로 얼마일까요?

 

위 질문은 같은 뜻이 됩니다.

 

2진수 8자리중 가장 작은수는 0000 0000  이므로 당연히 10진수 0(영)에 해당하며 가장 큰 숫자는 1111 1111 이므로 자리값들의 합을 모두 더하면 128 + 64 + 32 + 16 + 8 + 4 + 2 + 1= 255 가 됩니다. 물론 뺄셈 연산을 이용하여 쉽게 답을 맞추신 분도 계실껍니다.

 

자 그럼 한번 보도록 하겠습니다.

 

8비트로 나타낼수 있는 숫자는 0 ~ 255 까지 이므 경우의 수는 256개가 됩니다. 0을 포함하므로 표현할수 있는 가장 큰수인 255보다 하나더 많은 경우의 수를 가지는 것을 알수 있습니다.

 

그럼 숫자를 이야기 하다가 갑자기 경우의 수를 이야기해서 조금 의아해 하시는 분들이 계실 듯 합니다.

 

그럼 왜갑작스럽게 경우의 수를 이야기 하는가?

 

그 이유는 우리는 또다른 약속을 배우기 위함합니다.

 

앞서 8비트로 나타낼수 있는 크기 혹은 숫자는 0~255까지라고 말씀 드렸습니다.

 

그중 우리가 아는 약속중 하나인 ASCII 코드에서는

 

65를 대문자 A로 약속을 했었구요.

 

결론부터 말하면

 

0~255의 숫자를 표현할수 있다는 것은

 

0에 대한 약속

1에 대한 약속

2에 대한 약속

3에 대한 약속

.

.

.

255에 대한 약속

 

이렇게 총 256개의 약속이 가능하다는 것입니다.

(255개 아닙니다. 0도 약속 할수 있으므로 경우의 수는 256개 입니다.)

 

이를 문자표 약속으로 가정한다면

 

우리는 8비트 즉 숫자 0~255개의 경우의 수를 이용하여 문자 256개를 약속할수 있다는 뜻이기도 합니다.

 

그리고 다른 약속도 가능합니다.

 

너무 당연한 이야기 이지만...

 

2진수 0000 0000 은 숫자 0으로 약속을 하고

2진수 1111 1111 은 숫자 255로 약속을 할수 있습니다.

 

그런데 이 경우 문제가 생기게 됩니다.

 

모두 양수의 약속만 했지.. 음수의 약속을 하지 않았다는 것입니다.

 

그럼 컴퓨터가 음수를 사용하지 못하느냐?

 

그건 또 아닙니다.

 

다만 우리가 잘 아는 음수 기호 -를 붙여서 표현하는 방식이 아닌

위에 말한 경우의수 255개를 반드로 나누어서 음수를 표현하는 여러 방식들이 있습니다.

 

아주 간단하게는

2진수 맨 앞자리가 0이냐 1이냐로 음수와 양수를 구분하는 부호화 절대치 약속이 가능합니다.

 

부호화 절대의 경우

 

0000 0000 : +0

0111 0000 : +127 

1000 0000 : -0

1111 1111 : -127

 

이런 식으로 맨 왼쪽 자리의 숫자가 부호를 나타내게 하고 나머지는 크기를 나타내는 방식을 사용할수 있습니다.

 

다만 위 약속의 경우 매우 중대한 문제점이 있습니다.

 

보시는 바외 같이 +0과 -0이 존재하게 되는데요..

 

이 경우 소중한 약속의 공간 다르게 말해서 경우의수 1개를 낭비하게 됩니다.

 

결론적으로 0음 음수 양수가 존재하지 않으므로 1000 0000 이라는 약속 하나를 낭비하는 셈이며

컴퓨터 연산에서도 비 효율적입니다.

 

그래서 사람들은 보수라는 개념을 생각해 내게 됩니다.

 

보수에 대한 내용은 차차 설명을 드릴것이구요.

(쭉 설명하지 왜 자꾸 중간에 어려운 내용을 섞어서 설명 하다 말다 하다 말다하느냐?

다음 장을 이해하기 위한 부분만 설명하고 그렇게 설명을 드리는것이

이해도 쏙쏙되고 왜 어려운 내용을 배웠는가가 명확하기 때문입다.)

 

 

다시 본론으로 돌아와서.

 

8비트를 이용하면 256개라는 문자 약속이 가능하다는것을 방금 증명하여 드렸습니다.

 

그리고

앞서 우리는 컴퓨터는 문자를 알지 못하며 단순히 숫자만 기억할수 있다고 말씀 드렸습니다.

 

그럼 우리는 위 두가지 사실을 통하여 숫자만 기억할수 있는 컴퓨터도 문자를 어떻게든 표현해볼만하는 생각을 하시게 될껍니다.

 

이미 조금씩 설명을 드렸고 눈치 채셨겠지만

그 해답은 숫자를 문자에 대응시키는 문자표를 이용하는 것이며 대표적인 ASCII(아스키) 코드를 이용하는 방법입니다. 이 아스키 코드는 세계적으로 통용되는 약속이라고 생각하시면 됩니다.(실제로 약속입니다.)

 

앞서 보셨다 시피

쉽게 대문자 A를 숫자 65에 대응하여 생각하므로 대문자 Z는 얼마가 될까요?

알파벳은 총 26문자이며 현재 A가 65 이므로 남은 알파벳은 25개입니다. 그래서 대문자 Z는 65('A') + 25의 크기를 가진다고 생각할수 있습니다.

 

늘 이렇게 계산하면 어려우니깐 C 언어에서는 홋따옴표를 이용하여 알파벳이나 문자를 표현하면 컴파일러에서 알아서 자동으로 숫자값을 바꾸어 저장을 해주게 됩니다.

 

'A' + 1 = 66 기억 나시죠?

 

이는 아주 편리한 기능입니다.

 

예를 한번 보도록 하겠습니다.

 

cha ch;

ch = 'A';

 

printf("%d\n",ch);    // %d 65 출력

printf("%c\n",ch);    // %c A 출력

printf("%d\n",'A');   // %d 65 출력

printf("%d\n",'A'+1); // %d 66 출력

printf("%c\n",'A'+1);  // %c 65 출력

printf("%c\n",'A'+25); // %c Z 출력

printf("%d %d\n",'A', 'a'); 

 

찬찬히 쳐다 보시면

크게 문제없이 이해가 되실껍니다.

 

하지만 마지막 문장이 조금 어려울수 있을 것 같네요.

 

실제로 수행해 보시면 'a' 값을 정확하게 아실수 있을 껍니다.

 

결과를 말씀 드리면

 

위 값이 소문자 a를 컴퓨터가 기억하는 숫자 혹은 ASCII 코드의 숫자값에 해당합니다.

 

자 위 내용을 정확하게 이해하고 실습을 해보셨다면

 

printf("%d\n",‘a'-'A'); 

위 연산을 통하여 소문자 a와 대문자 A의 차이값을 컴퓨터에게 바로 물어보는 것은 어떨까요?

 

정답은 본인 스스로 한번 찾아 보시기 바랍니다.

 

 

그럼

여기서 문제를 한번 내보도록 하겠습니다.

 

char ch = 'a';

 

이때 ch변수에는 소문자 a가 들어 있는데 이것을 대문자 A로 바꾸고자 한다면 우리는 어떤일을 하면 될까요?

 

위 앞서 대문자 A와 소문자 a값을 직접 확인하셨을테니 그 차이 숫자만큼 더하거나 빼주면 ch 변수는 대문자 A로 바뀌게 될것입니다.

 

정답은 여러분들 스스로 직접 찾아 보시는것으로 하겠습니다.

 

그래도 정답 확인용 코드는 첨부하여 드릴께요.

 

곰곰히 생각해 보시고 소스코드를 참조하시면 되겠네요.

 

#include <stdio.h>
int main(void){

   char ch='a';
   char ch2 = 'a'; //위 ch 변수와 동일한값을 가지는 ch2 변수 선언 
   
   printf("a = %d, A=%d\n", 'a', 'A'); //소문자 a 대문자 A값을 직접 확인 
   
   printf("'a'-'A'=%d\n", 'a'-'A');  //그 차이를 뺄셈 연산을 통해서 확인 
   
   printf("ch-32 = %d\n", ch-32);//위 연산을 통하여 알라낸 차이값을 뻬주고 출력해서 확인함 
   
   printf("ch2-('a'-'A') = %d\n", ch2-('a'-'A')  ); //printf에서 직접 문자코드로 값을 빼줌 
   
   return 0;
}

 

 

 

 

 

우리는 앞서 치환이라는 개념을 배웠습니다. 이제 앞서 배운 단순한 치환 개념이 아닌 연산자들의 관계에서 치환이 어떻게 적용되는지 예제를 통해서 한번 살펴 보도록 하겠습니다.

 

 

#include <stdio.h>
int main(void){
   
   // 변수선언
   int num1; 
   int num2;
   int num3;

   // 초기화 및 연산
   num1 = 5;
   num2 = 7;
   num3 = num1 + num2; 
   num3 = num3 +1;
   printf("%d, %d, %d",num1, num2, num3);
   return 0;
}

 

* 출력서식에 “(쌍따옴표) 안에 포함된 ,(콤마)는 화면에 보여지기 위한 서식입니다. 출력서식과 출력 데이터를 구분하기 위한 구분자가 아닙니다. 

 

 

위 프로그램은 num1, num2, num3 라는 int형 정수 변수 3개를 선언하고 num1에는 5를 대입하고 num2에는 7을 대입하는 프로그램입니다.

 

대략 11번줄 까지는 쉽게 분석이 될것이라 생각합니다.

 

그럼 12번 줄부터 한번 살펴 보겠습니다.

 

num3 = num1 + num2;

 

위 문장은

 

num1 값이 5 이고 num2가 7이므로 

 

num3 = 5 + 7;

위와 같이 뜻을 가집니다.

 

결론적으로 num3 에는 숫자 12가 저장됩니다.

 

그런 다음 13번 라인 num3 = num3 +1 문장이 실행되게 됩니다. 앞서도 말씀 드렸지만 = 기호는 치환 연산자이지 수학에서 같다는 뜻이 아닙니다. num3과 num 3 +1이 절대로 같을수 없는것처럼 말입니다. 위문장은 num3의 값에 1을 더해서 num3에 다시 집어 넣으라는 뜻입니다.

 

 

num3 = num3 +1; 문장은

 

num3 = 12 +1; 과 같은 뜻입니다.

 

결론적으로  num3에는 13이 저장되며

 

printf("%d, %d, %d",num1, num2, num3); 문장이 실행될 경우

 

5, 7, 13 이라는 숫자라 화면에 출력 됩니다.

 

여기서 한가지 짚고 넘가야할 중요한 사실이 있습니다.

 

num1과 num2에는 초기값을 5와 7로 주었지만 num3에는 초기값을 주지 않았습니다. 그 이유는 num3는 계산에 의해 그 값이 완전히 결정되는 변수이기 때문입니다.

 

살짝 변형된 다음 예제를 한번 보겠습니다.

 

#include <stdio.h>
int main(void){
   
   // 변수선언
   int num1=5; 
   int num2=7;
   int num3=195;

   // 연산
   num3 = num1 + num2; 
   num3 = num3 +1;
   printf("%d, %d, %d",num1, num2, num3);
   return 0;
}

 

 

위 프로그램도 결과는 마찬가지로 5, 7, 13 이라는 숫자가 출력됩니다.

 

7번라인의 int num3=195; 문장을 통하여 num3의 초기치를 195를 주어도 프로그램 결과에는 아무런 영향을 미치지 않습니다.

 

그렇치요? 네 이런 변수를 저는 계산에 의한 변수라고 이야기 합니다. 계산에 의한 변수가 아닌 경우는 모든 경우에 초기치를 주어야 프로그램에 문제가 없습니다.

 

 

아래 프로그램을 다시 한번 보겠습니다.

 

#include <stdio.h>
int main(void){
   
   // 변수선언
   int num; 
   num = num + 1;
   printf("num : %d",num);
   return 0;
}

 

위 프로그램을 실행하면 작동은 하지만 화면에 이상한 값이 출력될것입니다. 제 컴퓨터에서는 방금 -85899330 이라는 음수값이 출력 되었습니다.

 

그 이유를 설명드리도록 하겠습니다. 

 

5번 라인에서 num 변수를 선언만 합니다. 어떠한 초기치를 넣지도 않았습니다. 그렇다면 과연 num 변수를 선언만 했을 경우 num 이라는 정수를 저장할수 있는 공간에 처음에는 어떤 값이 들어 있을까요? 0이라는 숫자가 들어 있으면 얼마나 좋겠습니까 만은 C 언어는 그렇치 않습니다. C 언어는 변수공간을 할당할 때 어떤한 작업도 하지 않고 오직 메모리 공간만 할당 한다는 것입니다.

이때 num 공간이 이전에 다른 프로그램에서 사용하던 공간이라면 그 공간에 어떤 숫자가 들어 있을지 알수 없다는 것입니다. 이를 우리는 가비지(쓰레기값)라고 이야기 합니다.

 

즉 현재 쓰레기값이 들어 있는데 6번 문장을 만나면

 

 num = 쓰레기값 + 1; 수행하는것과 마찬가지가 되어 결론적으로 num에는 쓰레기값보다 1큰 숫자가 저장되게 되고 화면에 출력되는 것입니다.

 

그래서 보통

 

좌항에 변수명이 나오고 우항에도 동일한 변수명이 나오는 형태

즉, 동일변수명 = 동일변수명 + 숫자(또는 다른 변수명) 형태일 경우 동일변수명은 반드시 초기화를 해주어야 한다는점 잊지 마시기 바랍니다.

 

다음으로 살펴볼 내용은 ++와 -- 연산자입니다. 일반적으로는 +1 연산과 같은 결과를 나타내지만 실제로는 더 빠른 속도로 연산을 수행하며 ++의 위치에 따라서 선증가인지 후증가인지를 결정하게 됩니다.

 

컴퓨터에서 +1을 하는 것은 덧셈 연산을 이용하여 가산기를 이용하지만 1 증가하는 것은 별도의 증가연산기(카운터)를 이용하므로 실제 덧셈연산 보다 훨씬 고속으로 이루어 지게 됩니다. 요즘은 컴퓨터 속도가 빨라져서 별 차이를 못느끼지만 +1하는 문장은 10만번 수행하게 될경우가 있다고 가정해 보면 ++ 연산을 10만번 하는 것이 더 빠르게 작동할것이라는 것은 너무나 자명한 일입니다.

 

좀더 자세하게 예를 들어서 설명해 보겠습니다.

 

#include <stdio.h>
int main(void){
   
   // 변수선언
   int num=3;
   printf("num : %d\n",num); // 3출력
   
   num = num + 1;
   printf("num+1후 : %d\n",num); //4출력
   
   num++;  //1증가
   printf("num++후 : %d\n",num);//5출력
   
   printf("printf num++ : %d\n",num++);  //5출력후 6으로 증가
   printf("printf ++num : %d\n",++num);  //7로 증가후 7출력
   printf("num최종 : %d\n",num);  //최종적으로 7 출력

   return 0;
}

 

 

실제로 num++ 과 num=num+1의 결과는 실제로 같지만 연산문 또는 출력문에 직접 사용할 경우 결과는 앞서말씀 드린 선증가 연산이냐 후 증가 연산이냐에 따라서 결과는 달라지게 됩니다.

 

우선 int num=3;에 따라서 num에는 3값이 들어가게 됩니다. 이때 printf문으로 확인해보면 3이 들어 있음을 알수 있습니다.

 

9번라인에서 num = num+1;을 통하여 num에 1을 더하면 num은 4가 되며 이때 printf문으로 확인해보면 4이 들어 있음을 알수 있습니다.

 

11번 라인에서 num++ 후 증가 연산을 통하여 1이 증가하여 5가 되었습니다.. 이때 치환문이나 출력문에 바로 사용한 것이 아니므로 별다른 의미가 없으며 단순히 num+1보다 속도만 빠르다고 보시면 됩니다. 이때 printf문으로 확인해보면 5가 들어 있음을 알수 있습니다.

 

14번 라인에서 printf("printf num++ : %d\n",num++); 문에서 주의 하셔야 합니다.

 

위 문장을 만나기전에 num에는 5가 들어 있었습니다. ++ 연산자가 num 뒤에 있으므로 후 증가 연산에 해당합니다. 후 증가 연산은 우선 연산문 또는 출력문의 연산을 모두 마친후에 num값이 1 증가 하므로 현재 가지고 있는 5을 화면에 출력하고난뒤 num이 1 증가하여 6이 됩니다. 결론은 화면에는 5가 출력되고 num은 6으로 증가한다는 것입니다.

 

15번 라인에서 printf("printf ++num : %d\n",++num); 문도 각별히 주의 하셔야 합니다.

위 문장을 만나기전에 14번 라인에서 화면에 5를 출력했지만 후 증가연산에 의해서 실제는 6이 들어 있는 상태에서 15번 라인을 만나게 됩니다.

15번 라인은 ++ 연산자가 앞에 있으므로 선 증가 연산에 해당하며 증가 연산이 먼저 수행된 다음 연산문 또는 출력문을 수행합니다.

현재 num에 6이 들어 있는 상태이므로 우선 증가 연산을 하게 되면 num은 7이 되고 printf문으로 화면에 num 값을 출력하면 화면에 7이 출력 됩니다.

 

마지막은 16번 라인에서 printf("num최종 : %d\n",num); 문을 사용하여 최종 printf문을 확인 하여도 마찬가지로 7이 출력됨을 알수 있습니다.

 

--연산도 마찬가지 방식입니다. --연산은 -1 연산과 연산 결과가 동일하며 선감소 연산과 후 감소 연산으로 나누어 집니다.

 

예제를 바꾸어서 조그만 설명해 보겠습니다.

 

#include <stdio.h>
int main(void){
   
   // 변수선언
   int num=10;
   int num2;
   num2=num;   //num2에 num값 10이 치환됩니다.
   printf("num : %d\n",num2); // 10출력
   
   num = num - 1; //num은 9가 됩니다. 
   num2=num;      //num값 9가 num2에 치환 됩니다.
   printf("num-11후 : %d\n",num2); //9출력
   
   num2=num--;  //num의 9값을 먼저 num2에 치환한 다음 num은 8로 감소
   printf("num--후 : %d\n",num2);//9출력
   
   printf("printf num2-- : %d\n",num2--);  //9출력후 8로 감소
   printf("printf --2num : %d\n",--num2);  //7로 감소후 7출력
   printf("num최종 : %d\n",num2);  //최종적으로 7 출력

   return 0;
}

 

 

출력결과

 

 

 

 

num : 10

num-11후 : 9

num--후 : 9

printf num2-- : 9

printf --2num : 7

num최종 : 7

 

 

한가지더 재미있는 예제를 보도록 하겠습니다.

 
#include <stdio.h>
int main(void){
   
   // 변수선언
   int num=10;
   int num2;
   num2=(num++)+1;
   printf("num : %d\n",num); // 얼마가 출력 될까요?
   printf("num2 : %d\n",num2); // 얼마가 출력 될까요?

   num2=(++num)+1;
   printf("num : %d\n",num); // 얼마가 출력 될까요?
   printf("num2 : %d\n",num2); // 얼마가 출력 될까요?

   return 0;
}
 
5번 라인에서 num변수에 10 초기치로 치환되었습니다.
 
7번라인 num++은 후 증가 연산자 이므로 10+1이 먼저 수행되어 num2에 11이 치환되고 num은 나중에 증가하여 11이 됩니다.
 
11번 라인에서는 ++num이 선 증가 연산이므로 num이 먼저 증가하여 12가 되고 12+1이 수행되어 num2에 13이 치환됩니다.
 
 
 
 
이제 우리는 별도로 학습은 하지 않았지만 연산을 사용하였습니다. 대표적으로 더하기(+), 빼기 연산을 사용하였습니다.
 
그럼 나누기 곱하기 연산은 어떻게 사용하는 걸까요? 키보드에 자세히 봐도 ÷ 연산자와 × 연산자기 보이지 않습니다. 
그렇다는 것은 C 언어에서는 다른 기호들이 위 연산자를 대신한다는 것을 유추할수 있습니다. 우선 곱하기 연산자는 *(shift + 8)연산자를 사용하며 나누기 연산자는 /(슬러쉬) 연산자를 사용합니다. * 연산자는 곱하기 형태와 비슷하므로 그렇다고 치더라도 / 연산자는 나누기 연산자와 전혀 닮아 있지 않습니다. 그런데 왜 나누기 연산자로 사용하는 것일까요?
산수에서 말하는 2분의 1을 적을 때 1/2 라고 적는 것을 보신적이 있나요? 2분의 1이라는 것을 1을 2로 나눈 것을 말하는 분수 형태입니다. 1/2 이나 1÷2나 모두 결과는 0.5로 동일 합니다. 그래서 컴퓨에서는 분수 형태의 슬러쉬는 나누기 연산자 대신에 사용합니다 모양만 다르게 생겼지 결과는 똑 같기 때문입니다.
 
자 그럼 조금더 깊게 들어가 보겠습니다. 앞서 1/2는 0.5라고 말씀 드렸는데요. 수학적으로는 맞는 이야기 이지만 C 언어에서는 틀린 이야기입니다.
 
printf("%d", 1/2)를 해보시면 결과는 0이라고 화면에 출력될것입니다.
 
예로 적절하지 못하니 다른 예제로 바꾸어 보겠습니다.
 
printf("%d", 7/2)을 실행하면 화면에 3.5가 아닌 3이 나타날것입니다.
 
왜 이런 현상이 벌어지냐 하면요 C언어에서는 어떤 자료형이냐에 따라서 연산후 결과가 어떤 자료형으로 나올지 정해진다는 규칙이 있습니다.
 
무슨 소린지 감이 잘 안오시지요. 우선 정리하면서 설명을 추가하여 드리도록 하겠습니다.
 
예1. 정수 (연산) 정수 --> 정수
예2. 정수 (연산) 실수 --> 실수
예3. 실수 (연산) 정수 --> 실수
예실수 (연산) 실수 --> 실수
 
위오 같은 결과를 가져다 줍니다.
 
숫자를 통해서 예를 들자면
 
7이라는 정수와 2라는 정수를 가지고 나누기 연산을 하면 예 1과 같은 형태가 됩니다.
 
정수 (연산) 정수 --> 정수
7       /    2   --> 3
 
자 그럼 왜 3인지도 한번 생각해 보겠습니다. 7을 2로 나누면 정확한 답은 3.5인데 결과가 정수로 나와야 하므로 소수점 0.5는 버리고 3만 화면에 출력을 해주는 것입니다.
 
네, 이렇게 설명하면 반은 맞고 반은 틀린 이야기입니다.
 
정확한 이유를 알기 위해서는 실제로 컴퓨터는 어떤 방식으로 연산을 하는지부터 이해를 해야 합니다. 우선 대부분의 컴퓨터는 더하기만 할수 있습니다.
 
거짓말!! 3-2물으면 1이라고 답해주던데요...?
 
네 물론 답을 해줍니다. 하지만 일반적으로 우리가 사용하는 컴퓨터는 뺄셈을 하는 기계를 만들면 비싸기 때문에 덧셈을 하는 덧셈기를 내장하고 있습니다. 이 덧셈기를 보수라는 녀석을 이용해서 더하기하면 신기하게도 뺄셈을 하는 효과를 낼수가 있습니다. 얼핏 들어 보셨는지 모르겠지만 1의보수 2의 보수라는 개념이 그래서 나옵니다. 일단 보수는 접어 두구요
 
그럼 컴퓨터는 곱하기는 어떻게 할까요? 눈치 빠른 분은 금방 아셨겠지만 덧셈을 반복하여 곱셈 효과를 냅니다. 아물론 곱셈하는 곱셈기를 만들면 되지만 이것도 곰셈기 만드는 가격이 비싸므로.... 보통은 덧셈의 반복을 이용합니다.
 
가령 4*5를 컴퓨터에 물으면 컴퓨터는 4을 다섯 번 더합니다. 그래서 20이라는 결과는 우리에게 알려 주는 것입니다.
 
그럼 최종적으로 나누기는 어떻게 할까요?
 
곱셈이 더하기를 이용했듯이 나누기는 뺌셈을 여러번 해서 나누기 효과를 냅니다. 곱하기와는 달리 나누기는 뺄셈을 몇 번해야 할지 알수 없습니다. 무슨말인고 하니..
 
4*5의 결과를 알기 위해서는 4를 몇 번이나 더할지 그 정확한 횟수 5를 금방 알수 있습니다. 그러나 나눗셈은 뺄셈을 몇 번해야 할지 알수 없고 오히려 뺄셈하는 횟수가 나누셈의 결과가 됩니다. 따라서 뺄셈을 할 때 뺄셈을 당하는 녀석(피제수)이 음수가되지 않는 범위내에서 뺄셈을 하고 그 횟수를 우리는 유식하게 몫이라고 하면 남는 숫자를 나머지 라고 이야기 합니다.
 
자 그럼 같이 한번 나누셈을 위한 뺄셈을 한번 해보도록 하겠습니다.
 
7/2의 결과는 알기 위해서는 컴퓨터는 
 
7-2를 수행합니다. 2를 빼고 나니깐 7은 5가 되고 뺄셈을 1회 한것입니다.
5-2를 수행합니다. 2를 빼고 나니깐 5은 3가 되고 뺄셈을 2회 한것입니다.
3-2를 수행합니다. 2를 빼고 나니깐 3은 1이 되게 뺄셈을 3회 한것입니다.
1-2를 하면 결과가 음수가 되어 버리므로 이제껏 뺄셈한 횟수 3이 7/3의 결과 즉 몫이 되고 나머지는 1이되게 됩니다. 현재로써는 남는 1 즉 나머지는 별의미가 없지만 나중을 위해서 기억은 해두도록 하겠습니다.
 
그럼 실제로 소수점이 나오는 실수의 결과를 얻기 위해서는 어떻게 해야 할까요? 예2, 예3, 예4와 같이
 
7/2 대신 7.0/2을 하거나 7/2.0을 하거나 7.0/3.0을 하게 되면 결과는 3.5를 얻을수 있게 됩니다.
 
그럼 이쯤에서 우선 정리해보면 사칙연산자 더하기(+), 빼기(-), 곱하기(*), 나누기(/)는 모두 배웠습니다. 이러한 연산자를 산술연산자라고 합니다.
 
추가적으로 특별히 알아야할 산술 연산자가 하나 더 있는데 % 기호를 사용하는 나머지 연산자입니다.나머지 연산자란 말그대로 나머지를 나타내는 연산자입니다.
 
예을 들어서 한번 설명해 보도록 하겠습니다.
 
printf("%d", 5%3);을 실행할 경우 화면에는 2라고 나타나게 됩니다. 5%3이란 5을 3으로 나누었을 때 나머지를 뜻하는 것으로 앞서 설명드린 /연산과 동일한 방식으로 작동하되 결과가 몫이 아닌 나머지를 되돌려 준다는 것 말고는 연산 방식에서 차이점은 없습니다.
 
정리하면 /은 나누기 연산자 즉 몫을 구하는 연산자 이며 %는 나머지 연산자 즉 나머지를 구하는 연산자입니다. %연산자가 특이한점은 정수 연산에서만 유효 하다는 것입니다.
 
5%3은 5와 3이 모두 정수이므로 가능하지만 5%3.0과 같이 실수로 나누어서 나머지를 구할수 없습니다. 나머지란 개념은 소수점 개념을 적용하지 않고는 더 이상 나눌수 없을 때 나누는 것을 중단하였을 때 남는 숫자를 나머지라고 하는 것으로 실수연산은 절대로 수행할수 없습니다. 왜 제가 이렇게 나머지 연산을 강조 하느냐 하면요 우리나라 초등학생들은 나머지 개념을 그나마 잘 이해하고 있지만, 중, 고, 대학생, 일반인들은 나머지 개념이 잘 없으십니다. 아니 실수 연산에 너무 익숙해서 잊어 버리고 계시더라구요.
 
실제로 저도 처음에는 그랬고 참담한 현실이지만 1/2를 하면 나머지가 얼마냐고 물었을 때 0.5라고 답하는 학생들이 다수 있을껍니다. 지금 제말이 웃지 못하는 분들이 계실꺼 같아서 다시 한번 설명 드리겠습니다.
 
1 나누기 2는 음수가 되지 않고 1에서 2를 몇 번 뺄수 있냐는 것인데 1-2하는 순간 -1 되어 버리므로 한번도 빼지 못합니다.
 
따라서 1/2의 몫은 0이되고 나머지는 1이 됩니다. 꼭 나머지 개념을 기억하시기 바랍니다. 특히나 이 나머지 연산자가 자주 사용되는 곳이 후일 배우게 되실 홀수 짝수 개념입니다. 짝수의 특징은 2로 나누었을 때 나머지가 0인 것을 짝수라고 하고 나머지가 1인 것을 홀수라고 합니다. 그냥 살짝 %연산자의 중요성을 강조하기 위해서 스쳐지나가는 정도로만 기억하시고 차후 정식으로 다시 소개 드리겠습니다.
 
이번에는 조금은 다른 산술 연산자 사용법에 대해서 알아 보겠습니다.
 
num = num + 1 과 같이 num이 치환연사자 좌우에 2회 나오는 경우 우리는 이것을 num += 1 이라는 형태로 줄여 적을수 있습니다.
 
변수명일때도 마찬가지입니다. 가령 sum = sum + num의 문장의 경우도 sum += num 과 같은 형태로 바꾸어 적을수 있습니다.
 
더 빠른 이해를 위해서 변수명을 a, b를 사용하여 표로 정리해 보도록 하겠습니다.
 

 

쉬운표현

다른 표현 방법

a = a + b

a += b

a = a - b

a -= b

a = a * b

a *= b

a = a / b

a /= b

a = a % b

a %=b

 

 

 

간단한 예제를 통해서 살펴 보겠습니다.

 

#include <stdio.h>
int main(void){
   
   // 변수선언
   int num1=10, num2=10, num3=10, num4=10;
   
   num1 += 5;  //num1 = num1 + 5
   num2 -= 4;  //num2 = num2 - 4
   num3 *= 5;  //num3 = num3 * 5
   num4 %= 4;  //num4 = num4 % 4

   
   printf("num1 : %d\n",num);
   printf("num2 : %d\n",num2);
   printf("num3 : %d\n",num3);
   printf("num4 : %d\n",num4);

   return 0;
}

 

위 프로그램을 이미 설명하였으므로 여러분들께서 직접 작성후 결과를 확인 하시기 바랍니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 



List of Articles
번호 제목 글쓴이 날짜 조회 수
공지 C언어 입문자를 위한 C언어 안내서 : 목차(모든 강의 링크 제공) 좋은아빠되기 2025.11.19 8
공지 C언어 입문자를 위한 C언어 안내서 : 필자의 말 좋은아빠되기 2025.11.19 5
14 무료 공개강좌 문제없다 C언어 강의 교재 다운로드 안내 file 좋은아빠되기 2015.11.22 2507
13 문제없다 C언어 문제 1 좋은아빠되기 2015.11.22 4037
12 문제없다 C언어 문제 2 좋은아빠되기 2015.11.22 1437
11 문제없다 C언어 문제 3 좋은아빠되기 2015.11.22 922
10 문제없다 C언어 문제 4 좋은아빠되기 2015.11.22 757
9 문제없다 C언어 문제 5 좋은아빠되기 2015.11.22 805
8 문제없다 C언어 문제 5-1 좋은아빠되기 2015.11.22 966
7 문제없다 C언어 문제 5-2 좋은아빠되기 2015.11.22 2592
6 1장. C언어와의 만남 : - 처음으로 만드는 C언어 프로그램 좋은아빠되기 2025.11.19 7
5 컴파일러 설치 임시본 좋은아빠되기 2025.11.19 4
4 1장. C언어와의 만남 : - printf는 명령어가 아니고 함수다! 좋은아빠되기 2025.11.20 5
3 C언어를 공부하지전 알아두면 피가 되고 살이 되는 컴퓨터 이야기 1(진법) 1 좋은아빠되기 2025.11.20 4
2 2장. 자료형에 따른 변수 선언 및 대입문과 연산자 : int, float, double, char 좋은아빠되기 2025.11.21 3
» 2장. 자료형에 따른 변수 선언 및 대입문과 연산자 : 2진법과 비트 그리고 바이트 좋은아빠되기 2025.11.21 4
Board Pagination Prev 1 Next
/ 1