구조체의 메모리 저장방식

2021. 3. 22. 00:43 기타/C언어

구조체의 메모리 저장방식을 알면 멤버변수들을 선언할때 좀 더 메모리를 효율적, 최적화되게 쓸 수 있다.

1. 구조체의 바이트 패딩

바이트패딩이란 멤버 변수를 메모리에서 CPU로 읽을 때 한번에 읽을 수 있도록, 컴파일러가 레지스터의 블록에 맞춰 바이트를 패딩해주는 최적화 작업이다. 만약 컴파일러가 패딩을 하지 않는다면(=최적화를 해주지 않는다면) CPU가 메모리에 다시 접근하면서 성능이 떨어질 것이다.

struct x {
  char a;
  int b;
  char c;
};

struct x data;

위 구조체를 sizeof(data) 로 찍어보면 6이 나올 것같지만 12가 나온다. 컴파일러는 구조체를 구성하는 멤버들을 가장 크기가 큰 멤버 자료형의 배수가 되도록 정렬한다. 이 정렬을 위해 의미없는 바이트(패딩)들을 붙이는 것이다. 따라서, 위 코드에서 컴파일러는 4바이트의 int형에 맞춰 멤버들을 정렬한다. 암묵적으로 a와 c 뒤에 3바이트씩의 패딩을 추가시켜주는 것이다.

struct x {
  char a;
  char b;
  char c;
};

위 구조체는 3바이트다. 가장 큰 멤버의 자료형의 배수 = 1바이트니까~~

struct x {
  char a;
  char c;
  int b;
};

struct x data;

위 구조체는 sizeof(data)로 찍으면 12가 아니라 8이 나온다. 이해를 돕기위해 그림을 그려보면

이런식으로 되는 것이다. 즉, 구조체의 메모리 저장방식을 알게되면 효율적으로 구조체 멤버를 선언할 수 있다!!

2. 전처리기 #pragma pack(n)

참조문서: https://msdn.microsoft.com/ko-kr/library/2e70t5y1.aspx

이 전처리기는 정수 n값이 넘을 경우, 정렬(=패딩 바이트 추가)을 포기한다는 거다. 즉, n값이하일 경우에만 정렬하려고 한다. n값은 1,2,4,8,16 만 유효하다. 이 전처리기를 쓰지 않았을 경우 디폴트값(n)은 8이다. 8바이트인 이유는 64비트 운영체제여서가 아니라 기본 타입중 가장 큰 타입이 8바이트이기 때문이다. 만약 int128_t같은걸 쓰는 시대가 온다면 16바이트로 바뀔 수도 있겠다.

#pragma pack(1)

struct x {
  char a;
  int b;
};

struct x data;

위 구조체의 sizeof(data)의 값은 5이다. 최고 크기가 4바이트이지만 전처리기에서 1바이트가 넘으면 정렬하지 않겠다고 했기 때문이다. 따라서 바이트 패딩이 일어나지 않는다.



출처: https://sjh836.tistory.com/35?category=680969 [빨간색코딩]