푸른나무그늘

마음이 쉬는 곳...

포토로그


QR CODE

이글루스 구글 검색엔진


Twitter


C언어 유니온(union)에서 구조체(struct) 선언 //프로그래밍//

소켓 통신을 하기 위해 패킷 타입을 정의하면서
명령어, 데이터 길이, 데이터로 나뉘어 있는 패킷을 좀 더 쉽게 다루기 위해 union으로 정의하였습니다.

[code1]

typedef union {
struct {
BYTE command[1];
BYTE length[4];
BYTE data[1400];
} Segment;

char buffer[1405];
} Packet;

이렇게 하면,
Segment 구조체와 buffer 변수가 메모리를 함께 사용하므로,
데이터를 쓰거나 읽을 땐 Segment의 각 변수를 쓰고,
소켓을 통해 보낼 땐 buffer 만 보내면 됩니다.

그런데 length에 int형을 넣으려고 하니, 조금 난감해지네요.
지금은 memcpy 함수를 이용하여 다음과 같이 int형 숫자를 length에 복사하였습니다.


[code2]

int testInt = 10;

memcpy(Packet.Segment.length, &testInt, 4);


문제는 이 전에 시도했다가 실패했던 방법인데, 이제야 왜 실패했는지 생각나서 적어봅니다.
방법은 union을 그대로 이용하는 방법이었습니다.

[code3]

typedef union {
struct {
BYTE command[1];
int length;
BYTE data[1400];
} TypeSeg;
struct {
BYTE command[1];
BYTE length[4];
BYTE data[1400];
} Segment;

char buffer[1405];
} Packet;

자, 이렇게 바꾸면 TypeSeg 구조체에 있는 int형 length에 바로 숫자를 입력할 수 있게 됩니다.
물론 처음부터 저렇게 하면 되지 않았을까 싶지만, 보낼 땐 buffer를 통채로 보내도
받을 땐 각 변수별로 받을 것이기 때문에 저렇게 선언했었습니다.

아무튼, 저렇게 선언했는데 실패했습니다. 왜일까요?

저도 겨우 기억났습니다.
struct 안에 선언하는 변수들은 워드 정렬(word-align)이라고 하여,
간단히 말하면 4byte씩 끊어서 선언된다는 것입니다.

예를 들어 위의 [code3]에서 TypeSeg와 Segment 구조체는 언뜻 보기엔 크기가 같아야 합니다.
그러나 실제로 sizeof 함수를 이용하여 보면 TypeSeg는 1408, Segment는 1405가 나옵니다.
정상적이라면 둘 다 1405의 크기가 나와야 되겠죠?

TypeSeg와 Segment 구조체의 차이점은 딱 하나입니다.
int형 하나와 4개의 BYTE형으로 된 배열.
결론을 얘기하면 int형은 4byte로 묶여서 선언되기 때문에,
1byte 크기의 command가 선언된 뒤, 뒤에 남아있는 3byte를 버리고(이를 패딩비트;padding-bit 라고 합니다.)
그 다음에 선언이 됩니다. 그래서 TypeSeg 구조체는 3byte의 패딩비트를 포함한 1408 크기가 나옵니다.

만약 선언 순서가 다음과 같이 바뀌었다면 크기는 똑같이 나왔을 겁니다.

[code4]

typedef union {
struct {
int length;
BYTE command[1];
BYTE data[1400];
} TypeSeg;
struct {
BYTE command[1];
BYTE length[4];
BYTE data[1400];
} Segment;

char buffer[1405];
} Packet;


이미 많은 분들이 알고 계시겠지만, 제가 또 까먹을까봐 적어봤습니다.
혹시나 누군가에게 도움이 된다면 더 좋구요. 그럼 이만-

핑백

  • 푸른나무그늘 : 2010년 내 이글루 결산 2010-12-27 11:49:43 #

    ... C언어 유니온(union)에서 구조체(str...</a>내 이글루 인기 글 가장 많이 읽힌 글 <a href="http://paulownia.egloos.com/4366254" style="color:#363636; width:px; overflow:hidden; text-decoration:underline;" target="_blank">C언어 유니온(union)에서 구조체(struct) 선언 ... more

덧글

  • 무바 2010/03/29 22:47 # 삭제 답글

    자주 까먹는 내용이지요:) 상기시켜주는 내용 잘 읽다 갑니다.:)
  • 푸른나무 2010/03/30 00:49 #

    나름 중요한 내용인데, 잘 신경쓰지 않아서 인지 자주 까먹게 되네요. ㅎ
  • 쿤이 2010/04/22 16:27 # 삭제 답글

    예리한부분 모르고 넘어가기 쉽겠군요 ^^ 잘보고갑니다~
  • 푸른나무 2010/04/23 16:07 #

    항상 sizeof를 쓴다면 좀 나아지겠죠? ㅎㅎ
    감사합니다.
  • 희돌군 2010/06/27 12:59 # 삭제 답글

    pack 을 쓴다면??? 프로토콜 정할 때 워드정렬 되지 않도록 하지 않던가?
  • 푸른나무 2010/06/27 13:10 #

    음, 그건 몰라서 안써봤는데, 나중에 써봐야겠다 ㅋ
  • 희돌군 2010/06/29 12:18 # 답글

    아! 그리고 4byte씩이 아니라 해당 구조체의 제일 큰 사이즈 기준으로 된다고는 하는데 요즘 컴파일러는 max가 4byte인듯... char a; short b; char c; 라고 하면 6byte 잡힐껄~
  • 푸른나무 2010/06/29 18:09 #

    32비트 사양에 맞춰서 컴파일러를 만든거 아냐? ㅋ
  • 하바람 2010/11/04 20:00 # 삭제 답글

    잘 보고 갑니다 ~~
  • 푸른나무 2010/11/04 20:00 #

    넵~!!
  • 전부다먹어 2011/04/18 12:15 # 삭제 답글

    순서가 command가 제일 밑으로 내려와야 같아지지 않나요?
    length, command, data로 선언해도 구조체의 사이즈는
    command, length, data로 선언했을때와 같이 parity를 처리해 1408이 되지 않나요?^^;
  • 푸른나무 2011/04/18 16:25 #

    따로 테스트 해보진 않았지만 (int)length, command, data로 선언하는 경우에는
    length에서 4byte선언이 되고, command와 data는 연속된 byte로 선언이 되기 때문에 1405byte가 됩니다.
    감사합니다. ^^
  • 제리스 2011/11/01 14:35 # 삭제 답글

    잘 보구 갑니다+_+!!!
    딱 제가 보고 싶었던 부분이네요. union을 배우기만했지 직접 써보진 않았는데, 쓰여져 있는걸 활용할려고 하니까 헷갈렸거든요.
  • 푸른나무 2011/11/01 14:56 #

    도움이 되셨다니 다행입니다. ^^
  • yuchi 2011/11/01 16:42 # 삭제 답글

    vc++에서 기본적으로 struct align은 4바이트입니다. global하게 바꾸려면 프로젝트 속성에 들어가서 바꿀 수 있습니다.
    통상 네트워크 프로그래밍에선 struct align이 문제가 될 수있기 때문에 코드 상에서 명시적으로 맞춥니다.
    #pragma pack(push,1)
    struct
    {
    ...
    };
    #pragma pack(pop)

    이런식이고 위의 예제는 1바이트 얼라인을 한것입니다. 네트워크 프로그래밍에선 패킷량을 줄이기 위해 보통 1바이트 얼라인을 합니다.
    struct align을 하는 주된 이유는 퍼포먼스 때문입니다. 캐쉬라인, 혹은 메모리 버스에서의 데이타 전송원리상 데이타버스의 비트수만큼의 align을 해야 추가적인 클럭 손실이 없기 때문입니다.


  • 푸른나무 2011/11/01 16:48 #

    좋은 정보 감사합니다.
    시간이 되는 대로 포스팅을 수정 해야겠네요. ^^
  • 베라모드 2013/09/11 17:55 # 답글

    좋은 내용 감사합니다. -_-
  • 푸른나무 2013/09/12 10:55 #

    ㅋㅋㅋ 도움이 되어 다행이군.
  • 2014/09/10 07:45 # 삭제 답글

    말을 게시하는 것은 너희들을 감사합니다! 너무 감사합니다!
  • 비페라 2015/05/22 17:24 # 삭제 답글

    현재 하는 거에 딱 필요한 정보였습니다 ㅋㅋ
    잘 보고 갑니당~
댓글 입력 영역



YES24