Notice
Recent Posts
Recent Comments
Link
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
05-17 00:00
관리 메뉴

nomad-programmer

[Programming/C] 구조체의 크기를 예측하지 말라 본문

Programming/C

[Programming/C] 구조체의 크기를 예측하지 말라

scii 2021. 1. 16. 01:35

구조체는 멤버 변수들의 크기에 따라 구조체의 크기가 결정되지만 구조체의 크기를 예측하여 동적 메모리를 생성하거나, 파일에 저장하거나, 네트워크에 전송하는 등의 작업을 하면 예상했던 구조체의 크기와 달라 오류가 발생하는 경우가 있다.

이유는 컴파일러가 프로그램 성능을 향상시키기 위하여 일정한 크기 형태로 구조체 변수들을 주소에 매핑시키기 때문이다.

매핑 : 패딩 바이트를 추가한 바이트 정렬

그래서 구조체의 크기는 모든 멤버 변수 크기의 합과 다를 수 있다.

다음은 구조체의 크기를 출력하는 예이다.

#include <stdio.h>

typedef struct {
    char c;
    int n;
} _data1;

typedef struct {
    short s;
    int n;
} _data2;

typedef struct {
    int n1;
    int n2;
} _data3;

int main(int argc, const char * argv[]) {
    _data1 d1 = {'a', 1};
    _data2 d2 = {10, 10};
    _data3 d3 = {100, 100};
    
    printf("%d %d\n", sizeof(_data1), sizeof(d1));
    printf("%d %d\n", sizeof(_data2), sizeof(d2));
    printf("%d %d\n", sizeof(_data3), sizeof(d3));

    return 0;
}


/* 결과
8 8
8 8
8 8
*/

위의 결과는 모두 8바이트가 출력된다. d1의 실제로 사용한 메모리는 5바이트, d2는 6바이트, d3는 8바이트지만 패딩 바이트가 자동으로 추가되어 사용되지 않는 부분이 만들어지며 d1, d2, d3의 크기가 모두 8바이트가 된다. 그러므로 구조체의 크기는 꼭 "sizeof" 연산자를 사용하여 크기를 구해야 한다.

만약, 구조체의 크기가 실제 멤버들의 크기와 같도록 주소를 매핑시키고자 한다면 전처리를 이용한 "#pragma pack()" 옵션을 설정할 수 있다. 하지만 좋은 방법은 아니다. 속도가 저하될 수 있다.

다음은 #pragma pack() 옵션을 사용하여 구조체의 크기를 출력하는 예이다.

#include <stdio.h>

#pragma pack(1)

typedef struct {
    char c;
    int n;
} _data1;

typedef struct {
    short s;
    int n;
} _data2;

typedef struct {
    int n1;
    int n2;
} _data3;

int main(int argc, const char * argv[]) {
    _data1 d1 = {'a', 1};
    _data2 d2 = {10, 10};
    _data3 d3 = {100, 100};
    
    printf("%d %d\n", sizeof(_data1), sizeof(d1));
    printf("%d %d\n", sizeof(_data2), sizeof(d2));
    printf("%d %d\n", sizeof(_data3), sizeof(d3));

    return 0;
}


/* 결과

(#pragma pack(1) 사용)
5 5 
6 6
8 8

(#pragma pack(2) 사용)
6 6
6 6
8 8

(#pragma pack(4) 사용)
8 8
8 8
8 8

*/

구조체 d1은 5바이트이고 d2는 6바이트, d3는 8바이트이다.

#pragma pack(1) 전처리기의 해석은 구조체를 1바이트 단위로 적재하라는 의미가되며, pack(2)는 2바이트 단위로 적재, pack(4)는 4바이트 단위로 적재하라는 의미이다.

Comments