본문 바로가기

# Lang/C++

2.2 자료형과 데이터 해석

 정수 해석

정수 자료형이란 정수를 나타내는 원시 자료형을 말하며,

컴파일 환경에 독립적인 int16_t,  int32_t,  int64_t를 표준으로 사용한다.

 

 

  • 부호있는 정수의 해석  (Signed Integer)

비트열을 부호화된 2의 보수로 해석한다. 

 

 

  • 부호없는 정수의 해석  (Unsigned Integer)

비트열을 절대값으로 해석한다. 

 

 

 

 

 부동소수점 해석

소수점이 둥둥 떠다닌다는 뜻으로,  부동소수점이라는 이름이 붙여졌다.

소수를 표현하는 원시 자료형.

 

정밀도에 따라 float(단정밀도),  double(배정밀도)로 나뉘며,

IEEE754 표준에 따라 비트열을 해석한다.

 

4 Byte 부동소수점 레이아웃 (Float 표준)
8 Byte 부동소수점 레이아웃 (Double 표준)

 

 

 

 

 구조체, 클래스 해석

클래스 내의 멤버변수는 메모리 상에서 일렬로 배치된다.

클래스 내의 멤버함수는 해당 클래스의 가상 테이블에 적힌다. 

 

자식 클래스의 멤버변수는 메모리 뒤에 순서대로 덧붙이고,

자식 클래스의 가상 테이블은 별도로 생성한다.

 

 

 

즉, 클래스의 멤버변수 형태만 같다면,

다른 클래스로 강제로 캐스팅해도 에러가 발생하지 않는다.

 

#include <iostream>
using namespace std;

class PublicBox {
public:
    int32_t a;
    void call(){
        cout << "I'm Public Box" << endl;
    }
};

class PrivateBox {
private:
    int32_t b = 5;
};

int32_t main(){
    auto * box1 = new PrivateBox;
    auto * box2 = ((PublicBox*)(void*)box1);
    // box1, box2가 가르키는 메모리 주소는 같지만.
    // box1 -> Private Box
    // box2 -> Public  Box

    box2->a;        // 5
    box2->call();   // I'm Public Box.

    delete box2;
    delete box1;
}

 

강제로 변환할 때,  함수의 구조는 일치하지 않아도 된다.

함수는 호출되는 시점에서, 해당 자료형의 가상 테이블을 확인하기 때문이다.

 

 

 

 

 구조체, 클래스 패딩

대부분의 컴퓨터는 4 Byte 단위의 읽기연산을 실행하며,

각 블럭의 첫번째 주소값도 4의 배수이다.

 

만약 연산단위에 맞춰 정렬되지 않은 데이터를 읽으면 어떤 일이 일어날까?

더 많은 읽기연산이 발생한다.

 

아래의 그림에서 연산단위에 정렬된 경우에는 2블럭만 읽으면 되지만,

그렇지 않은 경우에는 3블럭을 읽어야 한다는 것에 주목하자.

 

 

 

 

 

 암묵적인 패딩 

현대 컴파일러는 이러한 비효율을 줄이기 위해,

아래처럼 중간마다 의미없는 공간을 집어넣어 전체크기를 가장 큰 원시자료형의 배수 단위로 맞추고,

가장 큰 원시자료형의 크기에 맞추어 중간중간에 패딩을 삽입한다.

 

만약 클래스 내의 가장 큰 원시자료형이 8 Byte라면,

클래스의 전체크기를 8 Byte 단위로 맞추고,

앞에서부터 8 Byte의 틀에  집어넣으려고 노력한다.

 

아래는 가장 큰 멤버변수가 4 Byte이므로,

앞에서부터 4 Byte 단위에 맞춰 정렬한 모습이다.

 

 

 

 

 명시적인 패딩  (Since C++11)

사용자가 alignas 지정자를 명시하면,

컴파일러는 해당 크기에 맞춰 데이터를 정렬한다.

 

단, 사용자로부터 지시된 데이터의 크기가 부족하다면 무시되며.

암묵적 패딩과는 다르게  2^n 크기로만 정렬할 수 있다.

 

#include <iostream>
using namespace std;

class alignas(16) Box {
public:
    int32_t a;  // 4바이트

    int16_t b;  // 2바이트
    char c;     // 1바이트
    bool d;     // 1바이트

    bool e;     // 2바이트
    //          // 2바이트 패딩 추가됨.

    // 전체 12 Byte.
    // 하지만 alignas 지시자에 의해 16 Byte로 정렬됨.
};

int32_t main(){
    cout << sizeof(Box);    // 16
}

 

 

 

 

 공용체 해석

공용체는 하나의 메모리 영역을 모든 멤버변수가 공유하며 사용한다.

즉, 하나의 메모리 주소를 여러개의 방법으로 해석할 수 있다는 것 이다.

 

아래의 공용체는 int로도 해석할 수 있고, char[4]로도 해석할 수 있으므로,

val을 구성하고 있는 비트열을 4부분으로 쪼갠것이 ch[4]이 된다.

 

공용체는 데이터를 바이트 단위로 나누는 효과적인 방법이며.

비트필드와 같은 자료구조를 구현하는데도 도움을 준다.

 

 

 

 

'# Lang > C++' 카테고리의 다른 글

3.1 CV 제한자 (const, volatile)  (0) 2019.03.31
2.3 자료형과 형변환  (0) 2019.03.29
2.1 자료형  (0) 2019.03.26
1.3 변수와 메모리 모델  (0) 2019.03.23
1.2 변수의 생성  (0) 2019.03.21