[C/C++] Struct의 메모리 이해

Eugene CHOI·2022년 2월 4일
0

C/C++

목록 보기
5/9

Struct의 크기는 직관적이지 않다

다음과 같은 코드가 있습니다. 다음 코드를 실행하면 얼마가 나올까요?

#include <stdio.h>

struct Student{
    int a;
    char b[6];
    int c;
} Std1;

int main(){
    printf("Std1의 크기는 %d byte 입니다.\n", sizeof(Std1));
}
Std1의 크기는 16 byte 입니다.

우리 생각으로는 6 byte + 4 byte + 4byte = 14 byte가 나와야 할 것 같지만 실제로는 16 byte가 나왔습니다.

그 이유는 word에 있습니다.

Word란 컴퓨터에서 연산의 기본 단위가 되는 정보의 양을 의미합니다.

일반적으로 32bit CPU라고 하는 x86 아키텍처는 1Word=4byte입니다.
64bit CPU라고 하는 x86-32 아키텍처는 1Word=8byte입니다.
(이것은 절대적인 것은 아니니 예외가 얼마든지 있을 수 있습니다.)

컴퓨터는 word 단위로 데이터를 읽을 때 가장 효율이 좋습니다.
그래서 struct의 메모리 크기는 이 word의 배수로 잡습니다.
만약 4byte int 자료형이 최대 크기라면 4의 배수, 8byte의 double 자료형이 최대 크기라면 8의 배수로 이루어집니다.

그렇다면 4의 배수로 맞추고 남는 메모리는 어떻게 할까요? 그냥 빈 공간으로 비워둡니다. 이것을 Byte Padding이라고 합니다.

그렇기 때문에 위의 Student 구조체의 크기는 다음과 같이 메모리가 할당됩니다.

idx12345678910111213141516
\,aaaabbbbbb\,\,cccc

여기서 눈여겨 볼 것은 b변수 6byte 뒤에 두 칸의 메모리가 비어 있다는 것입니다.
이 공간을 Padding Byte라고 합니다. 또한 가장 마지막에 Padding Byte가 생기는 것이 아니라 멤버를 선언한 순서에 따라서 생깁니다.


구조체 크기 최적화

다음과 같은 예를 생각해 볼 수 있습니다.

#include <stdio.h>

struct Student{
    int a;
    char b[2];
    int c;
    char d[2];
} Std1;

int main(){
    printf("Std1의 크기는 %d byte 입니다.\n", sizeof(Std1));
}
Std1의 크기는 16 byte 입니다.

이 경우에는 메모리는 다음과 같이 할당됩니다.

idx12345678910111213141516
\,aaaabb\,\,ccccdd\,\,

Padding Byte가 2byte, 2byte 총 4byte가 생성됩니다. 만약 멤버 선언 순서를 바꾸면 어떻게 될까요?

#include <stdio.h>

struct Student{
    int a;
    char b[2];
    char d[2];
    int c;
} Std1;

int main(){
    printf("Std1의 크기는 %d byte 입니다.\n", sizeof(Std1));
}
Std1의 크기는 12 byte 입니다.

좀 전과 다르게 4 byte가 감소한 모습을 볼 수 있습니다.
이와 같이 메모리 배치를 고려한다면 같은 구조를 가지는 구조체라도 좀 더 효율적으로 메모리를 사용할 수 있습니다.

idx123456789101112
\,aaaabbddcccc

구조체의 정렬 바이트 기준

간혹 설명 중 "멤버 중 가장 큰 크기로 할당된다."라고 설명하는 경우도 있는데, 이해하기는 편하지만 엄밀히는 틀렸습니다.

#include <stdio.h>

typedef struct {
    int a,b,c;
} STRUCT_A;
typedef struct{
    STRUCT_A a;
    int b;
} STRUCT_B;

int main(){
    STRUCT_A a;
    STRUCT_B b;
    printf("size of A is %u byte\n", sizeof(a));
    printf("size of B is %u byte\n", sizeof(b));
}
size of A is 12 byte
size of B is 16 byte

위와 같은 경우가 있기 때문입니다.
STRUCT_A의 크기는 12 byte입니다. STRUCT_B의 크기는 16 byte입니다.
멤버 중 가장 큰 크기로 할당된다면 STRUCT_B의 크기는 24 byte가 되어야 할 것입니다.

구조체 정렬 크기 변경

다음 전처리기를 이용하여 특정 바이트를 기준으로 정렬되도록 변경할 수 있습니다. 일반적인 Applicaion을 만드는 경우라면 필요 없지만, 매우 한정적인 메모리를 가지는 임베디드 시스템을 만드는 경우에는 유용할 수 있습니다.

#pragma pack(Bytes)
profile
Hi, my name is Eugene CHOI the Automotive MCU FW developer.

0개의 댓글