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;
}