ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 0x02 변수와 자료형
    Legacy/C 2014. 12. 14. 04:25
    728x90

    지난 시간에 배운 상수에 이어서 오늘은 변수에대해 배워보겠습니다. 

     

    변수(Variable)는 말 그대로 변할 수 있는 수를 의미합니다. 변하지 않는 일정한 수인 상수와 대비되는 수로서 주로 프로그램에서 처리한 자료나 처리한 결과를 기억하기 위해 사용됩니다. 변수는 기억 공간을 차지하며 그 기억 공간을 확보하는 행위(메모리 할당)를 변수 선언이라고 합니다. 변수를 읽어오는 방법에는 2가지가 있는데 하나는 주기억장치의 주소를 사용해 읽어들이는 방법과 다른 하나는 변수명(식별자)를 이용해 그것을 주소대신 사용해 읽어들이는 방법입니다. 주기억장치의 주소에 관한 내용은 뒤에 배울 포인터에서 설명하겠습니다.

     

    변수명을 짓는데에는 몇가지 규칙이 있습니다.

    1. 영어 소문자와 대문자, 숫자 그리고 밑줄 문자(_)만 사용해 만든다.

    2. 영어 대소문자를 구별한다.(대부분의 컴파일러에서 구별합니다.)

      ex) Clock와 clock가 서로 다른 변수명으로 쓰일 수 있다는 말입니다.

    3. 첫 글자는 숫자로 시작할 수 없다.

      ex) 3sum과 같이 숫자로 시작하는 변수명은 불가능합니다.

    4. 변수명 내에 공백이 포함될 수 없다.

      ex) grade 1, grade 2 처럼 변수 도중에 공백을 넣을 수 없습니다. 공백을 대신하기위해 grade_1, grade_2 처럼 밑줄 문자를 사용합니다.

    5. 예약어를 사용할 수 없다.(예약어의 종류는 검색을 해보시면 나옵니다.)

      ex) C에는 미리 그 의미를 규정해 놓은 몇가지 단어들이 있는데 그것을 예약어(keyword)라고 합니다.

            char, int, double, if, for과 같이 미리 정의된 단어들은 변수명으로 사용할 수 없습니다.

    6. 가급적 31자 이하로 짓는다.(컴파일러에 따라 31자까지만 인식이 되는 컴파일러가 있으므로)

      ex) abcdefghijklmnopqrstuvwxyz1234567890라는 변수명과 abcdefghijklmnopqrstuvwxyz12345678bc라는 변수명은 어떤 컴파일러에서

            는 같은 변수로 인식됩니다. 그러므로 가급적 31자 이하로 작성하는것이 좋습니다.

     

    변수명을 정할 때는 아무 의미없는 변수명보다는 sum, average, grade 처럼 의미있는 변수명을 사용하는 것이 좋습니다. 수십개의 변수를 사용할 경우 그 변수의 의미를 알수없는 a, b, c같은 변수를 사용할 경우 어떤 변수에 어떤 값을 저장했는지 알기 어렵게되기 때문입니다.

     

    변수는 사용하기전에 먼저 선언을 해주어야한다. 변수를 선언하는 방법은 다음과 같습니다.

     

    자료형 변수명;

    ex) int a1, a2;

         char b1, b2;

     

    변수는 처음 선언되면 쓸모없는 값인 쓰레기값을 가지게 된다. 이 값을 그냥 사용하려고하면 경고가 나온다. 그러므로 쓰레기값을 사용하기 않기 위해서는 초기화라는 것이 필요합니다. 변수를 초기화하는 방법은 다음과 같습니다.

     

    ex) int a1 = 3, a2 = 5;

     

    이처럼 변수를 선언과 동시에 초기화 해줄 수 있다. 이처럼 선언과 동시에 초기화 하지 않더라도

     

    int a1;

    a1 = 3;

     

    으로 써도 됩니다.

    다음 프로그램을 작동시켜보고 각각의 변수에 어디서 어떤 값이 저장되는지 살펴봅시다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    #include <stdio.h>
     
    int main (void)
    {
        int a1, a2, a3;
        
        a1 = 10;
        a2 = 20;
        a3 = a1 + a2;
        
        printf("a1 = %d, a2 = %d, a3 = %d\n", a1, a2, a3);
        
        a3 = a2 / 2;
        
        printf("a1 = %d, a2 = %d, a3 = %d\n", a1, a2, a3);
     
        return 0;
     
    }

    차근차근 따라가다보면 쉽게 파악가능할 것입니다. 

     

    이제 자료형에 대해 알아볼 건데요, C에는 자료형이 크게 2개로 나뉘어 있습니다. 정수와 실수 이 두가지 인데요, 여기서 의문을 제기하시는 분도 있을 겁니다. 문자, 정수, 실수 이렇게 세가지가 아니냐고. 물론 겉으로 보기엔 그렇게 보이지만 메모리 할당공간에 있어서 C에 '문자형'은 없습니다. 이 내용은 나중에 예제를 통해 설명해드리겠습니다.

     

    위에서 문자형을 저장하는 자료형이 없다고는 했지만 이건 메모리 크기에서 나오는 이야기 일뿐 이해를 돕기위해선 문자, 정수, 실수 이렇게 세가지 형으로 자료형을 나누는게 좋습니다. 자료형의 종류는 다음과 같습니다.



    빨간색으로 된 글씨는 해당 자료형의 기본형이라는 의미입니다. 기본형이란 상수에 대해 특별히 자료형을 명시하지 않았을 때 적용되는 자료형을 의미합니다. 여기서 자료형이 중요한 이유는 기억공간을 효율적으로 사용하기 위해서 입니다. 날짜(1~31)를 표시할 때는 1바이트를 차지하는 char을 사용해도 충분합니다. 그런데 4바이트인 int 형을 사용한다면 나머지 3바이트는 낭비가 되고 맙니다. 이런 것이 한두개 일 때는 문제가 되지 않지만 수천 수만개의 데이터에 적용된다면 거기에 낭비되는 기억공간은 무시할 수 없을 겁니다.

     

    우선 문자형 자료형에 대해 알아보겠습니다.

    문자형에는 3가지 자료형이 사용됩니다.


     문자 자료형

    크기

    표현 범위 

     char

    1 바이트 

     -128 ~ 127

     signed char

    1 바이트 

     -128 ~ 127

     unsigned char

    1 바이트

     0 ~ 255


    여기서 unsigned char은 말 그대로 부호를 표시하지 않는 것입니다. 1바이트, 즉 8비트를 사용하는데 여기서 가장 왼쪽비트인 부호비트를 부호비트로 사용하지 않고 일반적인 비트로 사용해서 0000 0000 ~ 1111 1111 까지 나타낸 것입니다. (255 = 2^8 - 1)
     
    다음으로 정수형을 알아보겠습니다.
    위에 나와있는 표와같이 6개가 있습니다. 그중 short가 들어간 것은 2바이트를 사용하고 나머지는 모두 4바이트를 차지합니다. 그 수에 대한 범위는 한번 추측해 보시기 바랍니다. 이것 역시 signed는 부호비트가 있는 것이고, unsigned는 부호비트가 없이 일반비트로 사용된 것입니다. 4바이트이므로 32비트니까 계산해 보시면 되겠습니다.
    정수형 변수의 이해를 돕기위해 다음 프로그램을 작동시켜 보세요.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #include <stdio.h>
     
    int main (void)
    {
        unsigned char age = 97;
        int max = 2147483647;
        int max_plus_1 = max + 1;
        unsigned int super = max + 1;
        
        printf("age = %d\n max = %d\n", age, max);
        printf("max+1 = %d\n", max_plus_1);
        printf("super = max+1 = %u\n", super);
        
        return 0;
    }

    여기서 max는 int형의 최댓값인데요, 여기에 1을 더하면 어떤 일이 벌어지는지 알 수 있는 프로그램입니다. 2147483647에 1을 더했으니 

    2147483648이 되어야 할것같은데 결과는 -2147483648(int형의 최솟값)이 되버렸습니다. 그런데 그 밑에 있는 super의 값은 정상적으로 연산이 되었습니다. 여기서 max_plus_1 변수에 발생한 일을 오버플로(overflow)라고 하는데요, 여기서 super과 max_plus_1에 오버플로가 발생하고 안하고의 차이는 부호비트의 유무에 있습니다.

     

    2147483647의 경우 비트로 나타내면 011111111......11111111(1이 31개)로 나타날것이고

    여기에 1을 더하면 1000000000.......000000(0이 31개)가 될 것입니다. 그런데 가장 왼쪽에 있는 비트는 부호비트라고 했습니다. 1이면 음수인거죠. 그런데 음수중에 가장 작은 수가 바로 100000....000000(0이 31개)입니다. 하지만 여기서 부호비트를 사용하지않고 unsigned 형처럼 일반 비트로 사용한다면 2의 32제곱인 2147483648이 결과로 출력되는겁니다.

    정리하자면 비트 내에서의 연산은 정상적으로 이루어지지만 가장 왼쪽비트가 부호비트이므로 최댓값+1이 최솟값이 되어버린 겁니다.

     

    마지막으로 실수형입니다.

    지난시간에 상수에서 설명해드렸다시피 C언어에선 실수를 가수부와 소수부로 나누어놓았습니다. 물론 여기서도 가장 왼쪽비트는 부호를 나타내는 비트입니다. long double과 double은 같고 주로 쓰이는건 float와 double입니다.


     실수 자료형

    크기

    유효 자리수

    최솟값

    최댓값

    float 

     4바이트

     소숫점 이하 6자리

     -10^38의 근삿값

    +10^38의 근삿값 

    double

     8바이트

     소숫점 이하 15자리

     -10^308의 근삿값

    +10^308의 근삿값 



    가수에 10의 거듭제곱을 곱하는 형태이므로 가수부의 비트수에 따라 유효 자리수가 결정됩니다. double은 32비트이므로 물론 가수부의 비트도 더 많기 때문에 더 정확하게 자료를 저장할 수 있습니다. 실수데이터는 정확성을 필요로 하는 경우가 많고 요즘은 기억공간이 충분하기 때문에 float보다는 double을 더 많이 사용하고, 그 편이 더 안정적인 프로그래밍을 가능하게 해줍니다.

     

    이상으로 변수와 자료형 마치겠습니다.

    'Legacy > C' 카테고리의 다른 글

    0x03 입력과 출력 - 출력  (0) 2014.12.14
    [참고] 아스키코드표  (0) 2014.12.14
    0x01 상수  (0) 2014.12.14
    0x00 C강의시작&C언어란?  (0) 2014.12.14
Designed by Tistory.