세 번째 강의

Aritficial IntelligEnce SystEm	C Language Study

ais.daegu.ac.kr                                                                      2007.03.31

이번 주는 변수가 메모리에 어떤 모습으로 저장되는지와 변수의 형 변환에 대해 공부하겠습니다. 저번 주 내용의 연장된 내용이라 보시면 될 거예요.

아래 소스를 한번 보죠.

그림 1. 변수 선언과 초기화

이번 주도 아주 쉬운 소스죠. ‘3주나 지됐는데 아직 이런 소스나 보고 있다니~’ 라고 생각하지 마시고 끝까지 읽어주세요. 그럼 위 소스를 보고 한번 생각해 볼까요?

▪ c는 문자 상수 'a'라는 값을 메모리에 어떤 모습으로 저장하고 있을까요?

▪ i는 777이라는 값을 어떤 모습으로 저장하고 있을까?

▪ 그럼 double형인 d는?

하나하나 해결해 봅시다.

▪ c은 문자 상수 ‘a’라는 값을 메모리에 어떤 모습으로 저장하고 있을까요?

c는 char로 선언되어있네요. 그럼 메모리에 1바이트가 할당되겠군요. 그리고 나서 선언과 동시에 문자 상수 ‘a’라는 값을 대입 시켜주고 있네요. 'a'의 뜻은 문자 a라는 글자 자체를 나타내는 것입니다. 그럼 이제 십자 드라이버를 들고 컴퓨터를 뜯어 봅시다. 그리고 램을 분해 해봐요~ c 변수가 할당되어있는 주소를 찾으셨나여? a라는 문자가 들어있나요? 아무리 찾아봐도 a는 안보이죠? a는 어디로 갔을까?! 이쯤되면 똑똑한 병래가 한마디 하겠죠 “컴퓨터는 0하고 1밖에 몰라요~ 그러니깐 a를 2진수로 바꿔서 저장했을 거예요” 맞습니다. 컴퓨터는 0 이랑 1이란 숫자, 즉 모든 데이터 표현 및 연산을 2 진수로 처리합니다. 그럼 경진이가 한마디 합니다. “야! 거짓말하지 마! a는 문자라고~ 어떻게 2진수로 표현을 하니? 내가 그렇게 쉬워 보이니?!” 고등학교 때 였나요? 수학시간에 10진수를 2진수로 16진수를 2진수로 진법 변환에 대해 공부했었는데. 분명 a라는 문자를 2진수로 변환 하는 법은 못 배웠습니다. 근데 C는 어떻게 a를 이진수로 표현할까?

정답은 ASCII(American Standard Code for Information Interchange) 코드죠. 한번쯤 들어봤을 단어라고 생각되네요. 컴퓨터 내부에서의 문자 표현을 비롯해 컴퓨터 사이의 정보교환 또는 컴퓨터와 주변장치 사이의 정보교환을 위해 만들어진 것이라고. ASCII에 대해 좀 더 얘기하자면 ASCII code는 1Bytes 중에 7bit를 이용해서 모두 128개의 문자를 표현하는 것입니다. 이중에서 20H~7FH(10진수로 32~127)는 도형문자로서 영문의 대/소문자, 아라비아 숫자, 각종 문장부호를 표현하는데 사용되고 00H~1FH(10진수 0~31)는 기능제어문자로서 주변장치의 제어, 직렬통신제어 등에 사용된다. 라고 책에 상세히 설명되어있네요~ ^^

그리고 7bit에서 1bit를 추가시켜 8bit로 확장된 것이 Extended ASCII 로써 일반적으로 ASCII라고 하면 Extended ASCII를 뜻 한답니다. 여기에는 비 영어 문자와 그래픽 문자가 포함되어있습니다. 이제 감이 오는거죠? 문자 a는 ASCII 코드 표에 의해 해당되는 숫자로 변환되어 저장되는 겁니다. 그럼 메모리에 2진수로 저장이 가능하겠죠. 아래 그림을 보면서 정리 합시다.

그림 2. c 변수에 실제 저장 되어있는 값

메모리에는 01100001이라는 이진수로 저장되어 있는 걸 확인할 수 있습니다. 이는 ASCII 코드에 의해 a가 97이라는 숫자와 맵핑 되어있다 라는걸 나타내는거죠. 이제 첫 번째 궁금증이 풀리졌죠. 그럼 다음으로 넘어가겠습니다.

▪ i 는 777이라는 값을 어떤 모습으로 저장하고 있을까?

첫 번째 문제를 제대로 이해하셨다면 이번 문제는 쉽게 풀 수 있을거라 생각되네요. 일단 i는 int형이므로 메모리에 4Byte를 할당하겠군요. 컴퓨터는 모든 데이터를 2진수로 처리한다고 해으니 777을 2진수로 저장하게 됩니다. 그럼 아래와 같은 그림으로 나타 낼 수 있습니다.

그림 3. n 변수가 메모리에 저장된 모습

▪ 그럼 double형인 d는?

double형은 실수를 나태나는 자료형이져. 과연 일반 정수와 똑같은 모양으로 메모리에 저장될까요? 조금 애매하죠?! 정답부터 얘기하자면 다르다. 라고 말할 수 있습니다. 소수점 이상은 상위바이트를 소수점 이하는 하위바이트를 각각 사용합니다. 이에 대해서는 직접 알아보세요. double 형을 비트단위로 그리려니 힘들어요. -_-a

2번째 주제는 형 변환입니다. 형 변환에 대해서도 많이들 들어봤을 거라 생각 되는군요. 우선 형 변환이 무엇인지에 대해서부터 알아보죠. 형 변환이란 char형이 int형이 되거나 int형이 double형 데이터로 변환되는 것을 말합니다. 이러한 형 변환에는 크게 두 가지가 있는데 자동 형 변환(묵시적 형 변환)과 강제 형 변환(명시적 형 변환)이 있습니다. 아래의 소스를 봅시다.

그림 4. 자동 형 변환 예제

소스를 보면서 뭔가 이상하다는 느낌이 들죠?! 정수형을 저장 할 수 있는 int형 변수 n에다가 54.01이라는 실수를 저장하고 있네요. 과연 어떤 일이 벌어질까요? 다들 궁금궁금하죠~

int형은 4바이트인데 54.01이라는 double형 실수를 대입 할려고 합니다. 당연히 불가능하겠죠. double형은 8이트를 요구하니깐요. 결국 대입연산이 성립되기 위해서는 double형 데이터 54.01이 int형 데이터로 변환되게 됩니다. 이러한 변환은 자동적으로 발생되며 그 과정에서 소수부의 손실이 발생됩니다. 그러므로 결과적으로 n에는 5라는 값이 저장됩니다. 4번째 줄도 마찬가지로 int형 2177이라는 정수를 char형 c에다가 넣으려고 하니 문제가 발생되게 됩니다. char c 라고 변수를 선언하게 되면 앞 부분에 signed가 생략 된 거라고 앞 시간에 얘기했었죠. 그러므로 c는 -128에서 ~127까지의 숫자를 표현하게 됩니다. 그런데 2177이라는 int형 4Byte 정수를 1Byte에 넣으려고 하니 당연히 문제가 발생되겠죠. 아래의 그림을 보면서 설명 드리겠습니다.

그림 5. int 형 2177의 비트 단위 표현

위 그림은 int형 데이터 2177을 비트로 나타낸 그림입니다. 이를 char c에 대입을 하게 되면 자동 형 변환이 발생되는데 이때 상위 3바이트를 버림으로써 1바이트를 만들게 됩니다. 이로 인해 결과적으로 예상치 못한 결과를 가져오게 됩니다. 다음 그림을 봅시다.

그림 6. 형 변환 후의 값

형 변환 후에 변수 c에는 위의 값이 저장됩니다. 그럼 char c에는 얼마의 값이 저장될까요? 계산기로 출력해보니 이진수 10000001은 129군요. 과연 char c에는 129가 저장되어 있을까요? 한번 출력 해보시기 바랍니다. =>(-127) 그리고 MSB가 뭔지에 대해 조사 해 보시고. 음수의 값은 어떻게 저장하는지도 알아보세요. 가장 왼쪽 비트가 부호비트 2의 보수를 통하여 맨 왼쪽 1은 부호니까 - 고 0000001을 바꾸면 1111110+1 을 해서 127 따라서 -127이 나온다

그럼 다음은 그림 4의 소스 5번째 줄을 보죠. tmp3에 7 을 대입시키고 있네요. 이때까진 변수의 자료형이 대입 시키는 값보다 작아서 데이터의 손실이 일어났었는데, 이번엔 반대로 int형 정수 7을 double형 변수에 대입 시키고 있군요. 이때는 별 문제 될 것이 없습니다. 이유는 대충 아시겠죠. double형은 int형보다 표현할 수 있는 값의 범위도 넣고 메모리도 크니 데이터의 손실 없이 실수 7.00000으로 자동 형 변환 되는 것입니다.

이번엔 강제 형 변환에 대해서 알아보아요. 강제 형 변환은 말 그대로 프로그래머가 형을 강제로 변환 시키는 거예요. 우선 아래의 소스부터 보죠.

그림 7. 강제 형변 환 예제 1

위와 같은 경우에 f에는 얼마의 값이 저장될까요? 네 float f에는 2.00000이 저장됩니다.

왜 이렇게 되시는지 알겠죠? n과 i는 정수이므로 나눗셈을 한 결과가 2.5가 나오지만 소수

점 이상 상위 바이트의 값 2만 갖게 됩니다. 여기서 다시 2를 float형으로 저장하므로 자동 형 변환에 의해 실수형 2.00000이 출력되는 것이죠~ 그럼 강제 형 변환을 시켜볼까요?

그림 8. 강제 형변 환 예제 2

위 와같이 선언을 해주면 n을 float형으로 강제 형 변환을 시킵니다. 그럼 n는 실수형이 되겠죠. 이때 피연산자들(n과 i) 간의 자료형 통일을 위해서 i에서도 자동 형 변환이 발생하게 됩니다. 이처럼 기본 적인 산술 연산자(+, -, *, /)는 두 개의 피 연산자를 필요로 하는데 이 두개의 피 연산자의 자료형이 일치하지 않으면 자동 형 변환이 발생된다는 것입니다. 결과부터 말씀드리면 i가 int형에서 float형으로 자동 형 변환됩니다. 이처럼 산술 연산 과정에서 일어나는 형 변환은 데이터의 손실이 최소화 되는 방향으로 진행됩니다. 그래야만 데이터의 손실이 발생하지 않기 때문이죠. 예를 들자면 char형 변수와 int형 변수가 곱셉을 한다면 char형 변수는 int형으로 자동 형 변환 됩니다. 자기보다 큰 데이터형으로 자동 형 변환 되는 것이죠. 이로써 산술 연산 시에도 피연산자간의 데이터 형을 일치시키기 위해 자동 형 변환이 발생된다는 것을 알 수 있습니다. 어려운 내용은 아니죠? 이로 인해 float f에는 최종적으로 2.50000라는 값이 저장되는 것입니다.

형 변환은 뒤에서 배울 포인터에서도 나오게 되는 내용입니다. 어려운 내용은 아니지만 한번 정리 해놓으시면 포인터 부분에서도 쉽게 이해하실 수 있을 거예요.

이로써 오늘 내용은 마무리 하겠습니다. 강좌를 쓰면서 열혈강의 C프로그래밍 책을 많이 참고하고 있습니다. 더 자세하게 알고 싶은 분은 책을 참고하세요.

참고자료

✔ 열혈강의 C 프로그래밍 윤성우 저, 프리렉

✔ Teach Yourself C, 피터 에이컨, 비앤씨

✔ C로 배우는 컴퓨터 프로그래밍, 이규철 외, 홍릉과학출판사

✔ 유닉스 ▪ 리눅스 프로그래밍 필수 유틸리티, 백창우, 한빛미디어