오류가 있으면 댓글로 바로바로 지적해 주세요...
===================================================
#04.초보가 쓰는 C 언어 강좌
(메모리와 변수)

                04.01 메모리에 대해
컴퓨터는 크게 기억장치부분, 연산부분, 입출력부분으로 나눌 수 있습니다. 기억장치는 우선 메모리를 말하며 보조기억 장치로는 하드디스크 CD-ROM 같은 게 있고, 연산장치는 CPU를 말하며 (특히 ALU를 말합니다.) , 입출력부분은 키보드, 모니터처럼 우리가 컴퓨터를 조정하거나 그 결과를 보여주는 부분을 말합니다.
기억장치 중 메모리는 실행코드(프로그램언어를 컴파일 해둔 기계어)를 잠시 그 위에 옮겨둘 수 있고, 실행 결과를 저장할 공간을 제공합니다. 프로그램은 평상시에는 하드디스크 상에 있습니다. 사용자가 그 프로그램을 실행하면 운영체제가 알아서 메모리로 옮겨 주고, 결과를 저장할 공간을 실행프로그램을 봐가면서 메모리에 맞게 마련해 줍니다. 따라서 프로그래머는 이 프로그램은 이 공간이 필요하다고 말하기만 하면 됩니다. 그 때 사용하는 게 자료형이라는 것입니다.

                04. 02 기본 자료형(Builtin Data Type)
C언어에서 메모리를 얻기 위해서는 자료에 맞는 메모리를 요구해야 합니다. 자료형(Data Type)은 크게 정수형(Integer), 부동소수형(Floating point), 문자형(Character)으로 나눌 수 있습니다. 정수형은 말 그대로 정수를 다루고, 부동소수형은 실수를 문자형은 문자를 다룹니다. 그리고 그 형은 내부적으로 크기에 따라 또 다시 나누어집니다.
왜, 이렇게 자료형을 나눌까요. 첫째는 메모리를 효율적으로 사용하기 위해서 입니다. 당연히 효율적으로 사용해야 메모리를 적게 사용할 수 있겠죠.  또, 자료에 맞는 연산(계산)을 하기 위해서 입니다. 소수점 계산하는 곳과 정수를 계산하는 곳은 CPU 내에 따로 위치해 있습니다.

                04.03 변수(Variable)
  수학에서 많이 들었던 낱말입니다. 쉽게 말해 변하는 수입니다. 보통 수학에서 함수를 사용할 때 쓰는 x 같은 문자와 비슷한 개념입니다. 변수는 자료형과 같이 쓰입니다. int a; 처럼. 여기서 a 가 변수입니다. 우리는 a, 대신 다른 이름을 줄 수 있습니다. 바로 앞 강좌에 심볼 이름 붙이는 규칙이 있습니다. 그 규칙에 맞는 여러 이름을 줄 수 있습니다. int a; 처럼 이렇게 변수를 만드는 행위를 변수를 선언한다(declaration) 고 합니다. (정확히 더 따지고 들어가면 선언:declaration와 정의:definition을 명확히 구별해서 사용해야 하겠으나 그러면 처음 배우는 사람들에게는 머리 복잡하니 구별하지 않겠습니다.)

  변수가 변하는 수라는 말에 걸맞게 값을 여러가지 넣어 줄 수 있습니다. 당연히 사용하기 전, 맨 마지막에 넣어준 값만 기억하고 있습니다. 그리고 맨 처음 넣어주는 행위를 특별히 초기화 한다고 합니다.

                04.04 정수형
정수형에는 int, short, long 이 있습니다. 바로 앞 강좌에 키워드라는 주제를 가진 글에 이 세 가지가 다 있습니다. 여기서 가장 중요한 것은 int 입니다.
Project 를 만들어 다음 예제를 실행해 보세요 (Project 만들 줄 모르신다면 앞의 강좌를 다시 읽어보세요.)

-----------------------------------------------------------------------------
/*  예제 04.01 */
#include <stdio.h>
#include <stdlib.h>

int main()
{
        int var;         /*1) var 라는 정수형 변수 선언 */
  
        system("PAUSE");
        /* Visual C를 사용한다면 이 부분은 없어도 됩니다. */
          
        return 0;
}
-------------------------------------------------------------------------


컴파일 해서 실행하면 아직은 아무것도 안 나옵니다. 여기서  주석 1) 에서 int 형 변수 var 를 정의했습니다. 선언은 공간을 만들어 달라고 컴파일러에게 요구하는 것입니다(정확히는 definitio 이 그렇습니다. 아직은 그냥 패스...). int 대신 long, short 를 선언해 주어도 됩니다. 이제 더 나가서 값을 넣어 볼까요.

------------------------------------------------------------------------
/*  예제 04.02 */
#include <stdio.h>
#include <stdlib.h>

int main()
{
        int var;        /* 1) */
        var  = 1;        /* 2)값 대입 */
        
        printf("%d \n", var); /* 3) */
        
        system("PAUSE");
          
  return 0;
}
------------------------------------------------------------------------

1이 라는 값이 출력됩니다. 당연한 말이지만, 1이라는 값은 var 가 가지고 있던 값입니다.
주석 2) 에서 var 는 이제 1 이라는 값을 가지게 됩니다. 이것은 수학에서 미지수 var 에 1 이라는 값을 대입하는 것과 같다고 보시면 됩니다.

주석 3)에서는 var 가 가지고 있는 값을 출력하라고 요구합니다.
주석 3) 다시 써 보면
printf("%d \n", 1); /* 3) */
이라고 쓴 것과 같습니다. %d 는 문자형 변수 또는 상수를 출력할 때 사용하는 형식입니다.

주석 1) 과 주석 2)를 동시에 할 수도 있습니다.
int var = 1;
처럼 할 수도 있습니다. 이런면 정의와 초기화를 함께 할 수 있습니다.

  주석 2) 에서 1 이라는 값 대신 다른 값을 넣고 다시 컴파일 해서 실행해 보세요. 그러면 그 넣은 값이 출력 될 것입니다. 여기서는 1 대신 정수만 집어넣을 수 있습니다.

int 대신에 사용될 수 있는 자료형은 long 과 short 이 있습니다.
long var; 이라고 long 을 사용하면  주석 2) printf("%d \n", var); 대신에 printf("%ld \n",var) 라고 해주어야 합니다.
( % 다음에 붙는 많은 문자들이 생각을 혼란스럽게 할 지도 모릅니다. 그리고 그게 무엇하는지도 모르겠죠. 지금은 잠시 print 에 대한 생각을 접어두고 변수가 무엇인가 그리고 자료형이라는 게 무엇인가 하는데 생각을 집중해 주세요.)

보통 32비트 컴퓨터 시스템과 32비트를 지원하는 컴파일러에서는 short 2byte, int 4byte, long 은 4byte의 메모리 공간을 차지합니다. (물론 내가 앞에서부터 설명한 Visual C, Dev-cpp 는 이 조건에 따릅니다.) 그리고 int 는 CPU가 처리할 수 있는 알맞은 크기입니다. 그래서 보통 int 를 많이 사용합니다.

메모리 크기의 영향으로 저장할 수 있는 한계가 있습니다. Visual C 6.0 와 Dev-cpp 을 기준으로 short 은  -32768 ( - 2^15) 에서 32767 (2^15 - 1 ) 까지의  숫자만 표현할 수 있습니다.
int 와 long 은 -2147483648 (-2 ^ 31) 에서 2147483647 (2^31 - 1) 까지의 수만 표현 할 수 있습니다. ( 여기서 사용된 2 ^ 15 같은 기호는 2의 15승 이라는 거듭제곱 연산을 말합니다. 이는 C 형식의 표현방법이 아닙니다. 보통 컴퓨터 상에서 거듭제곱을 ^ 를 이용해서 표시합니다. )
한 번 그 이상의 값을 넣어보십시오.

------------------------------------------------------------------------
/*  예제 04.02 의 변형 1 */
#include <stdio.h>
#include <stdlib.h>

int main()
{
        short var;        /* 1) */
        var  =32768 ;        /* 2)값 대입 */
        
        printf("%d \n", var); /* 3) */
        
        system("PAUSE");
          
  return 0;
}
------------------------------------------------------------------------
이런 식으로 값을 넣는다면 의도한 대로 값을 출력하지 않습니다.


                04.05 부동소수형
앞서 배운 예제에서 주석2)만 조금 고치면  조금만 고쳐보겠습니다.
------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>

int main()
{
        int var;        /* 1) */
        var  = 1.1;        /* 2)값 대입 */
        
        printf("%d \n", var); /* 3) */
        
        system("PAUSE");
          
  return 0;
}
------------------------------------------------------------------------
이 때 var 에는 1.1 이라는 소수를 저장할 수 없습니다. 이 코드는 1 이라고 1단위 이하 소수단위가 잘려서 나옵니다. 1단위에서 버림 한다고 할까요. C 에서 소수(일본 컴퓨터 용어를 이용하자면 "부동 소수점(浮動小數點 )"[floating point] 라고 합니다. )를 다루기 위해서는 float, double, long double 을 사용합니다. 보통 float 는 4바이트, double 은 8바이트입니다.  (long double 은 visual c 에서 8바이트로 double 과 같습니다. 내부적으로 long double 을 double 로 바꾼다고 합니다. dev-cpp 는 long double 이 12 바이트입니다. 이건 저 조차 이해가 안가는 일이라서 조금 더 봐야 될 것 같군요. 이게 x86 시스템에서 가능한지 좀 의문이라서. )

float, double, long double을 묶어서 실수형이라고 부릅니다.

float 과 double 도 메모리의 영향으로 표현할 수 있는 수에 한계가 있습니다. float 은 십진수를 기준으로 유효숫자가 6자리에 1.17549435e-38 에서 3.40282347e+38F 수 사이의 수를 표시할 수 있습니다.( 여기서 e 라는 기호는 씨언어에서도 사용되는 기호로 지수를 나타낼 때 사용됩니다. 계산기에서 사용되는 형식과 동일합니다. ) ( 여기에 사용된 유효숫자와 범위는 float.h 에 정의된 define 문을 참조했습니다). 물론 - 부호에 대한 사용도 가능합니다.  double 은 10진수를 기준으로 15자리 유효숫자와 2.2250738585072014e-308 에서 1.7976931348623157e+308 사이의 값을 표현할 수 있습니다.( 더 자세히 알고 싶은 분은 IEEE754 규정을 찾아보세요. 나중에 마이크로프로세스라는 과목을 듣게 된다면 여기에 대해 배우게 됩니다.)

앞의 예제가 제대로 작동하기 위해서는 2군데를 고쳐야 합니다. 주석 1과 3을 다음과 같이 고쳐야 잘 작동합니다.
------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>

int main()
{
        double var;        /* 1) */
        var  = 1.1;        /* 2)값 대입 */
        
        printf("%f \n", var); /* 3) */
        
        system("PAUSE");
          
  return 0;
}
------------------------------------------------------------------------
이렇게 고치면 우리가 원하는 값 1.1을 출력해서 보여줍니다. 주석 1에서 double 대신 float을 사용할 수 있습니다.



                04.06 문자형
---------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>

int main()
{
        char var;        /* 1) */
        var  = 'A';        /* 2)값 대입 */

        printf("%c \n", var); /* 3) */
        system("PAUSE");
        return 0;
}
------------------------------------------------------------------------
이 예제는 A 라는 값을 출력합니다. 컴퓨터 안에서는 모든 데이터는 0과 1로만 표현합니다. 그래서 문자도 결국 숫자로 표현됩니다. C 에서는 기본적으로 아스키코드를 이용해 문자를 표현합니다. 'A' 는 65 라는 아스키 값을 대표합니다.
주석 (3) 을
printf("%d \n", 'A' ); /* 3) */
라고 고쳐보세요. 그러면 65 라는 값을 출력합니다. 앞에서 %d 는 정수를 출력한다고 말했습니다. 이번에는
printf("%c \n", 'A' ); /* 3) */
라 고쳐보세요. 바로 앞의 예제와 같이 영문자 A 를 출력합니다.
이번에는
  printf("%c \n", 65 ); /* 3) */
  라고 고쳐보십시오. 똑 같이 'A'라는 값을 출력합니다. 이 부분은 상수를 설명하는 곳에서 더 자세히 설명하겠습니다.

char 형은 일반적으로 1 byte이기 때문에 이 자체만으로 우리 한글을 표현할 수 없습니다. 아스키 코드표를 찾아보면 알겠지만 알파벳 대소문자, 숫자, 기호 정도 입니다. 나중에 배울 char 의 배열을 이용해서 표현하게 됩니다.


( 참고적으로 C 에서는 확장형(wide character) 문자타입이라는 것을 지원합니다. wchar_t 라는 형입니다. 이 부분은 오래된 컴파일러에서는 지원하지 않을 수 있습니다.
  이 확장형은 시스템마다 차이가 매우 크다고 합니다. 어떤 곳에서는 2바이트로 정의 되어 있고, 어떤 곳에서는 4바이트로 정의 되어 있다고 합니다. Visual Stdio 6.0에서는 2byte이고 GCC계열에서는 4byte로 나옵니다. 유니코드라는 것도 이 확장형 문자를 통해 표현 할 수 있습니다. 그런데 이 확장형을 많이 안 사용합니다. 저도 많이 안 사용해 어떤 게 이것을 출력하는지도 모르겠습니다. 그래서 저도 설명을 포기했습니다. 죄송합니다. 말했다시피 저도 초보입니다.
)

char 형이 조금 독특한게 char 형으로도 정수형을 저장할 수 있습니다. 1byte이기 때문에 일반적으로 -127 ~ 128 까지의 숫자를 저장할 수 있습니다.
주석 2를 고쳐 다음과 같이 숫자를 직접 대입할 수도 있습니다.
---------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>

int main()
{
        char var;        /* 1) */
        var  = 65;        /* 2)값 대입 */

        printf("%c \n", var); /* 3) */
        system("PAUSE");
        return 0;
}
------------------------------------------------------------------------



변수를 사용할 때, 주의사항이 있습니다. 조금 오래전에 만들어진 컴파일러에서는(Visaul Stdio 6.0 을 포함함) 변수 그리고 다음에 나오는 상수를 선언할 때는 꼭 블럭(중괄호로 둘러싸인 부분)이나 프로그램의 첫 부분에 나와야 합니다. C99 를 지원하는 컴파일러에서는 이것에 대한 제한이 없으나 조금 오래된 컴파일러는 이것을 에러로 인식합니다. 그래서 다음과 같은 경우  컴파일이 안 될 수 있습니다.
-------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>

int main()
{
        printf("Hello, world\n");
        int var;        
        var  = 1;        
        
        printf("%d\n", var);
        system("PAUSE");
          
  return 0;
}
------------------------------------------------------------------------
나중의 for 문을 배우다 보면 이게 조금 답답해 보일 수도 있습니다.





끝으로 정리하겠습니다. 기본 자료형에는 정수형, 실수형(또는 "부동소수형"이라고 부르기도 합니다.), 문자형이 있습니다. 이 중 정수형에는 short, int , long 이 있고 이 중 int 형을 가장 많이 사용합니다. 실수형에는 float, double, long double 이 있고 이 중 double 형을 일반적으로 가장 많이 사용합니다. ( float 도 많이 이용하지만 long double 은 특수한 경우를 빼고는 거의 이용하지 않습니다.) 문자형으로는 char 형이 있고 이는 아스키 문자 하나를 담을 수 있습니다. char 형은 정수형 숫자를 담을 수 있기 때문에 정수형으로도 이용할 수 있습니다.


다음은 상수를 배우기로 하겠습니다.


  참고사항
  #1 32 비트 컴퓨터란??
  요즘에 64비트 CPU가 일반 PC 용으로 나왔다는 말을 들어보신 적 있나요? 컴퓨터에 붙는 16비트, 32비트 이런 컴퓨터가 무엇을 뜻하는지 알고싶지 않습니까?
사실 이런 분류를 나누는 게 꽤나 어렵습니다. 정확한 정의가 없을 뿐더러 제품을 판매하는 회사에서 악용할 여지도 많습니다.
일반적인 정의를 말하면 CPU안에 ALU 라는 정치가 있습니다. 이 장치 연산을 하는 장치입니다.  ALU에서 한 번에 계산할 수 있는 비트로 16비트,32비트 등으로 나눕니다. (한 번이라는 말도 약간의 왜곡이 생길 수 있을 것 같군요. 한 번이라는 말이 꼭 한 clock 을 의미하는 말은 아닙니다.)
다른 정의에서는 CPU 와 메모리 사이에 왔다갔다할 수 있는 비트의 수를 말합니다.  또, 다른 정의도 많았는데 기억이 안 나고요.

정확한 32비트 컴퓨터가 되려면 이 모든 것이 32비트면 되겠죠..

그리고 컴퓨터만 32비트라고 해서 32비트 모두를 사용할 수는 없습니다. 운영체제가 따라와주어야 하고, 그 운영체제 안의 프로그램도 32비트를 지원해야합니다. 더블어 우리 입장에서는 컴파일러도 32비트를 지원해야 32비트 프로그래밍을 할 수 있습니다.

  #2 C언어에서 선언(Declarations)과 정의(Definitions)
  다음은 C 프로그래밍을 만든 Dennis M.Ritchie 의 책"The C Programming Language" 186페이지 정리한 내용입니다.
  선언 : 기억장소를 할당하지 않는다.
  정의 : 기억장소를 할당하는 선언

조금 덧 붙이자면 나중에 배울 include를 이용할 때 이러한 변수가 다른 헤더파일에 있다는 것을 알리는게 정의이고 그냥 일반적으로 이런 변수를 앞으로 사용하겠다고 요구하는게 선언입니다. (물론 같은 헤더파일안에서도 정의를 사용해야 하는 경우가 있습니다. 서로 순환적인 구조를 같는 구조체의 경의가 이 경우입니다.)
이 강의에서는 이런 부분까지 세세히 구별하지 않았습니다.
초보자의 경우 이런부분까지 설명하면 머리아플 것이니 그냥 넘어가는 게 좋을 것 같군요.(솔직히 저도 얼마전에 안 사실입니다. )



덧 글(덧붙이는 글)
자료형에 정수형과 문자에 대해 unsigned 형이라는 게 있습니다. unsigned int . unsigned long, unsigned short, unsigned char 같은 식으로 쓰입니다. 이 형은 0과 양수에 대해 저장하도록 하여 넣을 수 있는 값을 범위를 2배로 늘렸습니다. 그런데 이런 거 까지 설명하면 처음 배우는 사람에게 너무 부담을 주는 것 같아서 뺏습니다.
또 여기서는 일반적인 32비트 컴파일러를 기준으로 자료형의 크기를 설명했습니다. C에서 정의하고 있는 자료형의 크기는 short <= int <= long 으로 되어 있습니다. 그래서 일반적인 16비트 시스템에서는 short, int 를 2바이트로, long을 4바이트 되어 있습니다.

작성자         : 한밀(승룡)
버전         : 0.1.5

이 글은 계속 고쳐지고 있습니다.
2003년 12월 어느 추운 날
최종 수정일 : 2007년 7월 중순, 날씨가 더워 잠을 못 자고 있는 어느 날




***** ljh131님에 의해서 게시물 복사 + 카테고리변경되었습니다 (2007-08-03 14:17)