앞장에서 우리는 재미있는 사실을 하나 발견하였습니다.
대문자 '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
0 0001
위와 같은 숫자들이 합해진 형태라는 것을 알수 있습니다.
자 그럼 자리값들을 표시해 볼까요?
1 0000 <-- 2의 4승 자리, 10진수 16에 해당합니다.
0 0000 <-- 2의 3승 자리, 10진수 8에 해당합니다.(어차피 0이라 의미는 없지만)
0 0100 <-- 2의 2승 자리, 10진수 4에 해당합니다.
0 0010 <-- 2의 1승 자리, 10진수 2에 해당합니다.
0 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 +000 0001
------------------
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;
}
|
쉬운표현 |
다른 표현 방법 |
|
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;
}
위 프로그램을 이미 설명하였으므로 여러분들께서 직접 작성후 결과를 확인 하시기 바랍니다.