data padding에 대한 고찰

곰개구리·2026년 7월 25일

평화로운 코딩노예 라이프
버전통합 중 노예는 묘한 구조체를 하나 찾았어요.

struct E {
    short a1;
    short a2;
    int a3;
    int a4;
    char *a5;
    struct C  *c_ptr;
    char a6;
    struct D {
        short e1;
        short e2;
        char e3;
    } d_info;
    short a7;
    short a8;
    void *a9;
    char padding[4];
}

요런 놈이었더랬죠.
끝의 padding이 거슬리지 않나요? 저거 왜 넣은거지 하는 생각도 들고요.
괜히 혼자 삔또가 상한 노예는 메모리 크기를 분석해봤어요.
참고로 메모리 크기는 이렇게 알 수 있어요.

구조체 내부의 메모리 구성

  • 원시 자료형의 경우 본인 크기의 n배수 위치에만 존재할 수 있다
  • 복합 자료형인 경우는 해당 자료형 재귀적 내부의, 가장 큰 원시 자료형 크기의 n배수 위치에만 존재할 수 있다.

구조체 자체의 메모리 구성은.

  • 해당 구조체 재귀적인 내부 가장 큰 원시 자료형 필드의 n배수 위치에만 존재할 수 있다.

뇌피셜이 아니고 그렇게 표준에 적혀있어요

Aggregates and Unions
Structures and unions assume the alignment of their most strictly aligned component. Each member is assigned to the lowest available offset with the appropriate alignment.
The size of any object is always a multiple of the object‘s alignment.
An array uses the same alignment as its elements, except that a local or global
array variable of length at least 16 bytes or a C99 variable-length array variable always has alignment of at least 16 bytes.4 Structure and union objects can require padding to meet size and alignment constraints. The contents of any padding is undefined.

그런 것으로 알고 구조체 크기를 계산해보면

struct E {
    short a1;  // total: 2 (byte)
    short a2;  // total: 4
    int a3;  // total: 8
    int a4;  // total: 12
===> 4 byte implict padding  // total: 16
    char *a5;  // total: 24
    struct C  *c_ptr;  // total: 32
    char a6;  // total: 33
====> 1 byte implict padding // total: 34
    struct D {
        short e1;  // total: 2
        short e2;  // total: 4
        char e3;  // total: 5
====> 1 byte implict padding
    } d_info;  // structure: 6, total: 40
    short a7;  // total: 42
    short a8;  // total: 44
====> 4 byte implict padding, total: 48
    void *a9; // 56
    char padding[4]; // total: 60
====> 4 byte implict padding, total: 64
}

대락 이런데. 벌써부터 화가 나지 않나요? 구조체의 크기는 가장 큰 필드인 포인터(8 bit) 의 n배수여야 하는데. 4바이트 패딩을 넣어버려서 뒤에 implict padding이 붙어버렸네요.
과연 제정신으로 만든 구조체일까요?

분노를 덮어두고. 기본적으로 레거시에 대한 무한신뢰를 가지고 있는 저는 저 패딩이 의미없는 값이 아닐거라는 생각을 했지요.

아무리 그래도 패딩을 넣는다면. 메모리 정렬 기준을 이해하고 있는 사람일텐데, 저런 얼탱없는 실수를 할 거라고 생각되지도 않았고요.

그래서 히스토리를 찾아봤더니 아하! 이전 구조체는 아래와 같았답니다.

struct E {
    short a1;  // total: 2 (byte)
    short a2;  // total: 4
    int a3;  // total: 8
    int a4;  // total: 12
===> 4 byte implict padding  // total: 16
    char *a5;  // total: 24
    struct C  *c_ptr;  // total: 32
    char a6;  // total: 33
====> 1 byte implict padding // total: 34
    struct D {
        short e1;  // total: 2
        short e2;  // total: 4
        char e3;  // total: 5
====> 1 byte implict padding
    } d_info;  // structure: 6, total: 40
    short a7;  // 42
    short a8;  // 44    
    char padding[4];  // total: 48
}

역시 이전 구조체의 경우 padding이 의미있게 들어있었어요. 그렇다면 범인은 누구일까요? 아하 일년정도 전 누군가가 필드를 추가했네요.
그 코드가 바로 이겁니다.

struct E {
    short a1;  // total: 2 (byte)
    short a2;  // total: 4
    int a3;  // total: 8
    int a4;  // total: 12
===> 4 byte implict padding  // total: 16
    char *a5;  // total: 24
    struct C  *c_ptr;  // total: 32
    char a6;  // total: 33
====> 1 byte implict padding // total: 34
    struct D {
        short e1;  // total: 2
        short e2;  // total: 4
        char e3;  // total: 5
====> 1 byte implict padding
    } d_info;  // structure: 6, total: 40
    short a7;  // 42
    short a8;  // 44
====> 4 byte implict padding, total: 48
    void *a9; // 56
    char padding[4]; // 60
====> 4 byte implict padding, total: 64
}

메모리 정렬에 대한 이해 없이, 왜 padding field가 존재하는지도 모른채로, 그냥 본인 필요한 필드를 하나 쑥 넣어버려서 구조체가 개판이 났어요.
화난거 아닙니다. 그럴 수 있죠.

좀 더 생각을 했다면

struct E {
    short a1;  // total: 2 (byte)
    short a2;  // total: 4
    int a3;  // total: 8
    int a4;  // total: 12
===> 4 byte implict padding  // total: 16
    char *a5;  // total: 24
    struct C  *c_ptr;  // total: 32
    char a6;  // total: 33
====> 1 byte implict padding // total: 34
    struct D {
        short e1;  // total: 2
        short e2;  // total: 4
        char e3;  // total: 5
====> 1 byte implict padding
    } d_info;  // structure: 6, total: 40
    short a7;  // 42
    short a8;  // 44
====> 4 byte implict padding, total: 48
    void *a9; // 56
}

이렇게만 했어도. 더 깔끔한 구조였을텐데 말이에요.
다시 말하지만 화난 거 아닙니다.

profile
개굴개굴 곰개굴

0개의 댓글