정의된 프로토콜의 구조체 크기가 다르네요!
글쓴이: namj99 / 작성시간: 화, 2007/11/20 - 10:11오후
각각의 형을 찍어보면,
char: 1
signed int: 4
signed long int: 4
unsigned char: 1
unsigned int: 4
unsigned long: 4
double: 8
float: 4
찍히는데,
구조체 전체를 sizeof로 찍어보면.
4, 8, 16, 32...바이트 차이가 나네요!
char형 5개가 들어있는 구조체를 한쪽에서는 5byte로 찍고,
다른 한쪽에서는 8byte로 찍네요.
구조체를 패킹해야 한다고 들은것같은데, 어떻게 해야하나요?
구조체 정렬을(alignment) 어떻게 맞춰주는지 좀 알려주세요!
Forums:
#pragma pack(1) 하시면
#pragma pack(1) 하시면 됩니다.
컴파일러마다 조금씩
컴파일러마다 조금씩 차이가 있는데요.
표준이 있는지 잘 모르겠습니다.
아무튼 구조체 내의 패딩때문입니다.
어떤 컴파일러는 #pragma pack(1)을 써주면 되고
( 필요시에 #pragma pack(push), #pragma pack(pop)을 같이 사용합니다. )
어떤 컴파일러는 structure 선언 앞에 __packed를 써주면 되며,
gcc의 경우는 struct abc { .. } __attribute__((__packed__)); 로도 됩니다.
구조체를 변경할 수
구조체를 변경할 수 있다면 구조체를 4 byte 단위로 구성되게끔 패딩하는 것도 한 방법은 되겠습니다. 위의 경우라면
char: 1
char: 3 (<- 3 byte padding)
signed int: 4
signed long int: 4
unsigned char: 1
char: 3 (<- 3 byte padding)
unsigned int: 4
unsigned long: 4
double: 8
float: 4
데이터가 늘어나는 게 단점이긴 하지만, 패킹 안해도 동일한 크기가 나오게 할 수는 있습니다.
하지만, 프로토콜에서 정의되는 구조체라면, 보통 전송 전/후에 serialize/unserialize 해서(적절한 크기의 메모리를 할당한 후, 각 필드별로 htonXX()/ntohXX() 를 사용해서 필드별로 데이터 복사) 전송하는 게 더 확실한 방법일 것입니다.
요 방법은 64비트
요 방법은 64비트 머신에서 컴파일 할 때 문제가 되지 않나요??
어디서 64비트 머신의 컴파일러는 8바이트 단위로 패딩을 한다는 내용을 본적이 있습니다.
일반적인 정렬
일반적인 정렬 규칙은 most restricted data type 을 기준으로 하기 때문에 구조체에 어떤 타입이 포함돼있는가에 따라 정렬 제한이 달라지므로, 32 비트 플랫폼에서도 double 형이 포함된 구조체는 8바이트 단위가 됩니다.
또한 항상 정렬 규칙이 most restricted data type 을 기준으로 한다고 볼 수도 없기 때문에, 몇바이트가 패딩될 것인지 예측하는 것은 잘못된 방법입니다.
말씀하신 직렬화를 사용하는게 가장 좋은 방법이라고 봅니다. pack 은 C 표준도 아니므로, 옵션이 지원되지 않을 수도 있으니까요.
Orion Project : http://orionids.org
댓글 달기