구조체의 정렬 요구사항은 가장 큰 멤버의 타입을 따른다.
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