구조체 패딩

sesame·2022년 2월 7일
0

교육

목록 보기
26/46

구조체의 정렬 요구사항은 가장 큰 멤버의 타입을 따른다.

ex) 구조체에서 가장 큰 타입이 32비트 정수이고 4바이트 단위로 정렬된다면 이 구조체 역시 4바이트 단위로 정렬되어야한다.

구조체는 각 멤버가 그 타입의 요구사항에 맞게 적절히 정렬될 수 있도록 패딩(채워넣기)이 필요하다.
따라서 (4byte 단위로 정렬되는)int 멤버가 (1byte 단위로 정렬되는)char 멤버 다음에 나온다면 컴파일러는 둘 사이에 3바이트를 채워넣어 int가 4바이트 정렬에 맞춰지도록 한다.
프로그래머는 종종 구조체 멤버 위치를 오름차순으로 조정해서 패딩에 소모되는 공간을 최소화하기도 한다. gcc 옵션인 -Wpadded를 사용하면 컴파일러가 패딩을 채워넣을 때마다 경고를 발생시켜 불필요한 패딩을 줄일 수 있는지 확인할 수 있도록 도와준다.

구조체 패딩 때문에 memcmp()나 bcmp()로 두 구조체가 동일한지 비교하는 것은 신뢰할 수 없다.

-> 구조체의 정렬은 가장 큰 멤버의 타입을 따르기 때문에 1byte 단위로 정렬되는 char 멤버 다음에 4byte단위로 정렬되는 int 멤버가 온다면 컴파일러는 둘 사이에 3byte를 채워넣어 int가 4byte 정렬에 맞춰지도록하는데 이 때 채워넣은 3byte(패딩)에 초기화되지 않은 값이 들어 있어서 실제로 두 구조체의 멤버가 같을지라도 다르다고 판단할 수 있다.



++++

구조체 패딩 연습

#include <stdio.h>
#include <string.h>

typedef struct A{
    int Size;
    short Cmd;
    int Count;
}A;

void RecvStruct(char* StructToChar){
    int Size = ((A*)StructToChar)->Size;
    short Cmd = ((A*)StructToChar)->Cmd;
    int Count = ((A*)StructToChar)->Count;

    printf("Size: %d\n", Size);
    printf("Cmd: %d\n", Cmd);
    printf("Count: %d\n", Count);
}

int main(void){
    char msg[8192];
    int i = 0;
    A StructA;

    StructA.Size = 1;
    StructA.Cmd = 2;
    StructA.Count = 3;

    RecvStruct((char*)&StructA);

    char *tmp = NULL;
    tmp = (char*)&StructA;

    printf("---------------------------------------\n");
    printf("struct size: %ld, %ld, %ld\n", sizeof(StructA.Size), sizeof(StructA.Cmd), sizeof(StructA.Count));
    printf("padding size: %ld\n", sizeof(StructA));
    printf("tmp size: %d, %d, %d\n", ((A*)tmp)->Size, ((A*)tmp)->Cmd, ((A*)tmp)->Count);
    printf("tmp all size: %ld\n", sizeof(tmp));
    printf("---------------------------------------\n");

    int len = sizeof(StructA);
    for(i=0; i<len; i++){
        strncpy(msg+i, tmp+i, 1);
    }
    printf("size: %ld, %zu\n", sizeof(msg), strlen(msg));

    for(i = 0; i<13; i++){
        printf("[%d] %d\n", i, tmp[i]);
    }
    printf("---------------------------------------\n");
    for(i = 0; i<13; i++){
        printf("[%d] %d\n", i, msg[i]);
    }

    printf("---------------------------------------\n");

    int Size = ((A*)msg)->Size;
    short Cmd = ((A*)msg)->Cmd;
    int Count = ((A*)msg)->Count;

    printf("Size: %d\n", Size);
    printf("Cmd: %d\n", Cmd);
    printf("Count: %d\n", Count);

    return 0;
}
Size: 1
Cmd: 2
Count: 3
---------------------------------------
struct size: 4, 2, 4
padding size: 12
tmp size: 1, 2, 3
tmp all size: 8
---------------------------------------
size: 8192, 1
[0] 1
[1] 0
[2] 0
[3] 0
[4] 2
[5] 0
[6] 0
[7] 0
[8] 3
[9] 0
[10] 0
[11] 0
[12] 0
---------------------------------------
[0] 1
[1] 0
[2] 0
[3] 0
[4] 2
[5] 0
[6] 0
[7] 0
[8] 3
[9] 0
[10] 0
[11] 0
[12] 0
---------------------------------------
Size: 1
Cmd: 2
Count: 3

0개의 댓글