by CodeJin19
1 min read

Categories

Tags

Structure Representation

  • 구조체는 메모리 블럭으로 표현한다.

    • 구조체의 모든 변수들을 충분히 포함할 만큼의 크기


  • 멤버변수들의 메모리 위치는 선언된 순으로 할당되어 정렬된다.

    • 다른 정렬 방식이 구조체의 메모리를 줄일 수 있다고 해도 선언된 순으로 정렬된다.

    • 다시 말해, 컴파일러가 구조체의 메모리 최적화를 하지 않는다.


  • 컴파일러가 구조체의 전체 메모리 크기와 각 변수의 위치를 정한다.


Alignment

구조체의 변수들을 메모리에 바로 할당하면 메모리 접근 시 시간이 많이 걸린다. 예를 들어, 구조체를 다음과 같이 선언했다고 하자


struct S
{
    char a;
    int x;
    char b;
    int y;
};


구조체 S의 메모리 시작 주소를 m이라고 할 때, char a는 m + 0에, int x는 m + 1에, char b는 m + 5에, int y는 m + 6에 있다. 이 경우, Memory Access에 더 많은 자원이 소요된다. 따라서 컴파일러가 변수 사이에 빈 공간을 추가하여 메모리를 정렬한다.


정렬 방식은 각 변수형 크기의 배수에 맞춰서 정렬한다. 예를 들어, char형 변수는 크기가 1바이트이므로 m + (1의 배수)에 맞춰 정렬하고, int형 변수는 크기가 4바이트이므로 m + (4의 배수)에 맞춰 정렬한다. 위의 경우, char a는 m + 0에, int x는 m + 4에, char b는 m + 8에, int y는 m + 12에 배치되고, m + 1부터 m + 4까지, m + 9부터 m + 12까지는 공백이 생긴다.


구조체의 메모리 크기를 줄이기 위해서는 멤버변수를 선언할 때 변수형 크기가 큰 것부터 작은 순으로 선언하면 줄어든다. 위의 경우, 구조체 하나에 16바이트였지만, 아래와 같이 바꾼다면 구조체 하나의 크기는 10바이트로 줄어든다.


struct S
{
    int x;
    int y;
    char a;
    char b;
};


구조체를 메모리에 할당할 때는 메모리 변수형 중 가장 큰 크기의 배수에 맞춰서 정렬한다. 이 글의 구조체 S의 경우는 4의 배수에 맞춰 정렬한다.


컴파일러가 구조체 크기를 줄이기 위해 멤버변수들을 재정렬하지 않는 이유는 다양하다. 첫째로 구조체가 다른 컴파일러에 의해 컴파일 될 수 있기 때문이다. 외부 라이브러리를 사용하는 경우가 있을 수 있다.


둘째로 맴버 변수가 다른 형으로 접근될 수 있기 때문이다.

struct S1
{
    char c;
    int i;
    char d;
};

struct S2
{
    char c;
};

void func (struct S2 *p)
{
    char x = p->c;
}

int main ()
{
    struct S1 a;

    func(&a); //S1 구조체를 받아도 이상이 없지만, S1 구조체를 컴파일러가 재정렬하면 compile error 발생

    return 0;
}