ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 데이터 타입 (1)
    프로그래밍언어 2020. 5. 1. 20:55
    728x90

    프로그래밍 언어에서의 데이터 타입은 어떻게 하면 현실세계의 데이터 구조를 프로그래밍 세계에 잘 반영할까에 대한 생각에서부터 출발했어요

     

    C언어의 데이터 타입 카테고리

    • Scalar type
      • Arithmetic type
        • Integral type
          • integer  ( short, int, long, unsigned ... )
          • char 
          • enumeration
        • Floating-point type (float, double ... )
      • Pointer type
    • Aggregate type
      • array
      • structure
    • Union type
    • Function type
    • Void type

    이외에도 2진수 10진수, int, float 상관없이 숫자면 다 numeric type

    0 또는 1의 값만 가지는 boolean (or logical) type

    character type 등으로 분류하기도 해요

    Numeric-Type1

    흔히 말하는 int 형으로 맨 왼쪽 첫 비트를 sign bit, 나머지를 absolute value 로 표현합니다.

    음수의 경우 2의 보수로 표현합니다.

    Numeric-Type2

    float, double 로 실수를 표현하는 타입들입니다. 마찬가지로 맨 왼쪽 첫 비트를 부호 비트, 8비트를 지수부, 23비트를 가수부로 취급하여 실수를 표현합니다.

    Numeric-Type3

    10진수 (decimal) 형으로, C언어 개발자에겐 생소한 타입입니다.

    숫자 16을 일반적으로 프로그래밍 언어에서는 2진수로 바꾼 뒤(10000) 이를 메모리에 넣는 방식을 쓰지만

    Decimal 타입에서는 1과 6을 각각 2진수로 표현합니다 ( 00010011 ) 그리고 이를 메모리에 넣는 방식을 씁니다. 이런 방식을 BCD(Binary Coded Decimal) 이라고 합니다.

    이렇게되면 사람은 10진수에 익숙하기 때문에 10진 값을 효율적으로 처리할 수 있지만 컴퓨터는 16가지 경우의 수를 표현할 수 있는 4비트로 10가지 경우의 수만 표현하게 되므로 낭비가 되게 됩니다.

     

    BCD를 왜 쓰냐?

    실수 표현에 오차가 사라집니다.

    부동 소수점 표현 방식은 지수부 가수부를 통해 실수를 표현하기 때문에 0.1 같은 수를 표현하려면 무한소수로 내려가게 돼요.

    반면 BCD 를 통해 표현하게 되면 0.1  ->  0.0001 로 표현할 수 있죠.

    Boolean Type

    사실 0과 1을 표현하기 위해서 1비트면 충분하지만 boolean 타입을 지원하는 언어들은 내부적으로는 4바이트를 사용합니다.

    우선 기본적으로 비트는 메모리 주소로 표현되지 않습니다. 메모리는 모두 바이트 단위로 움직이기 때문이죠. ( 1004.1번지 라는 표현이 없습니다 )

    따라서 굳이 1비트만을 쓰기 위해서는 32비트 컴퓨터는 한 번 데이터를 가져오면 4바이트 단위로 가져오게되고, 맨 앞 31비트를 날린 뒤에 값을 불러오고, 마찬가지로 값을 저장할때도 31비트를 보존하면서 마지막 1비트만을 수정하는 과정이 매우 골치아프죠

    그것보다는 4바이트로 0 또는 1로 관리하는게 속도면에서는 더 빠를것입니다. (메모리 낭비는 좀 있겠지만요)

    Character Type

    문자도 결국엔 내부적으로는 숫자 값이지만 ASCII 코드라고 하여 숫자 50 은 알파벳 'a'이다. 51은 'b'이다 와 같이 약속을 해둔 표가 있어요

    모든 컴퓨터가 이 표준에 따르기에 50을 숫자로 출력해줘(%d) 하면 50이 출력되고, 50을 문자로 출력해줘(%c) 하면 이 표를 기반으로 'a'를 출력해주는거에요

    String Type

    String 은 C에서는 기본적으로 제공하지 않는 데이터 타입이에요. char 형 배열과 \0 문자를 통해서 간접적으로 문자열을 지원하죠

    언어 자체적으로 String 을 Primitive type 으로 제공하는 언어들도 존재해요

    String 을 고정 크기 방식(fixed size) 으로 제공할지 동적 크기 방식(variable size) 으로 제공할지에 대해 언어 설계 레벨에서 고민을 하죠

    Fixed length string

    Fortran 같이 고정 길이 방식의 문자열을 제공하는 언어들은 같은 길이의 문자열들끼리만 연산이 가능해요.

    이런 언어들은 문자열을 처음 선언할때 길이를 명시하는 방식을 쓰고있어요.

    Limited dynamic length string

    C / C++ 이 이 방식을 쓰고 있습니다. 배열을 선언하여 최대 길이를 주어주고, 중간에 \0 문자를 넣어 문자열의 끝을 구분해주고 있죠

    Dynamic length string

    자바, 자바스크립트가 쓰는 방식이에요. 문자열의 길이를 런타임에 늘리고 줄일 수 있다는게 특징이에요

    대신 이렇게 되면 Runtime descriptor 가 필요하게 돼요. 일종의 헤더 같은건데 본 문자열의 길이나 주소 같은 것들을 따로 명시하는거죠

    무엇보다 내부적으로 문자열들의 Linked List 로 관리해요. 길이 10짜리 문자열을 저장하기 위해 배열 10칸을 잡아뒀는데 concatenate 되어 문자열이 15글자가 된다면 배열 15칸을 새로 할당 받지 않아요. 매번 그렇게 했다간 복사하는데 엄청난 비용이들거에요

    따라서 새로 추가된 5글자만을 위한 5칸짜리 배열을 만들어 저장한 뒤 10글자 String 뒤에 Linked list 로 이어 붙이게 돼요

    Ordinal type (셀 수 있는 타입)

    Enumeration types

    가능한 모든 경우의 값을 명시해두고, 골라 쓰는 타입.

    typedef enum {
    	mon, tue, wed,
    	thu, fri, sat, sun
    } DAYS;

    predecessor, successor, order 연산이 가능합니다.

    predecessor(tue)   ->   mon
    successor(tue)     ->   wed
    order(tue)         ->   1

    mon 부터 0에 할당되어 sun 은 6이라는 값을 갖게 되는데요

    C언어에서는 다음과 같은 연산이 허용됩니다.

    DAYS day1 = mon;
    DAYS day2 = tue;
    int x = day1 + day2;
    
    printf("%d", x);

    월요일과 화요일을 더한다. 그럼 수요일인가요..? ㅋㅋ

    enum 간의 이상한 연산인데 C언어에서는 내부적으로 int 로 관리하고 있기 때문에 다음과 같은 연산을 허용하는거에요

    타입 체킹에 엄격한 다른 언어들은 이와 같은 연산을 허용하지 않는답니다.

     

    enum 은 별칭 시스템을 이용하는것이기 때문에 적절한 이름과 operation 사용 시에는 가독성신뢰성을 향상시킬 수 있지만

    잘못쓰게되면 프로그램을 어렵게 만들 수 있으니 주의하여 사용해야 합니다.

    Subrange types

    C언어에는 없는 타입인데요. 변수의 표현 범위를 프로그래머가 명시할 수 있는 타입이에요

    var a : 1 ... 200;    // 1 ~ 200까지만 표현 가능한 변수 a

    이런식으로 표현이 가능하다고 해요. 이외의 값이 들어오게되면 에러를 내게 됩니다.

    Runtime 에 범위 검사를 하기 때문에 느려지긴 하지만 안전한 프로그래밍을 할 수 있게됩니다.

     

    다음 포스팅에서는 배열 타입에 대해서 더 알아볼게요

    댓글

Designed by Tistory.