Qaupot Blog
Software Engineering, Trip

411. 공용체

🕐 Sun, 09 Feb 2014 09:00:00 GMT 🕓 Tue, 24 Aug 2021 08:36:00 GMT

공용체 (Union)

공용체는 "모든 멤버변수가 같은 메모리 공간을 가지는 자료형"입니다.
다시 말하면 "하나의 메모리 공간을 서로 다른 자료형의 형태로 읽을 수 있도록 하는 자료형"이기도 합니다.

#include <stdio.h>

union IntDivider
{
    int IntValue;
    char CharValue[4];
};

int main(int argc,char** argv)
{
    IntDivider Divider; 
    Divider.IntValue = 0x10203040;
    printf("Int : %x\n",Divider.IntValue);
    printf("Byte : %x %x %x %x\n",Divider.CharValue[0],
                Divider.CharValue[1],Divider.CharValue[2],
                Divider.CharValue[3]);

    union 
    {
        int IntValue;
        char ByteValue[4];
        short WordValue[2];
    };

    IntValue = 0x40302010;
    printf("Int in Anonymous union: %x\n",IntValue);
    printf("Byte in Anonymous union : %x %x %x %x\n",ByteValue[0],
                                    ByteValue[1],ByteValue[2],ByteValue[3]);
    printf("Word in Anonymous union : %x %x\n",WordValue[0],WordValue[1]);

    return 0;
}

Union 의 선언

union 의 선언은 다음의 형태를 따릅니다.

union (이름)
{
 (공유하고자 하는 자료형들)
}

IntDivider 라는 이름을 가진 union 이 선언되어 있습니다. 멤버는 IntValue 와 CharValue 로 되어 있습니다.

main 함수의 가장 첫 부분에서 이 union 을 이용해 Divider 라는 이름의 변수로 선언 했습니다.

  • 어떠한 자료형이 되었든 Divider 는 변수이며, 당연히 메모리 공간을 가지고 있습니다.

union 은 자신이 가지고 있는 멤버중 가장 큰 자료형의 공간만큼 크기를 만들어 냅니다.
위의 경우는 IntValue 가 int 형으로 4byte 이며 CharValue 가 char 형으로 1byte 이면서 4개이므로 4byte 입니다.
따라서, 4byte 의 공간이 스택 메모리 공간에 배정됩니다.

Divider 에 0x10203040이란 16진수 값을 대입합니다.
16진수는 두 자리당 하나의 byte 를 의미합니다.

  • 16^2 = 256, 2^8 = 256

아래 출력문을 보겠습니다.
Divider.IntValue 는 같은 값이 출력 됩니다.

그리고 밑에, 별도로 값을 넣지 않은 Divider.CharValue 역시 값이 출력되고 있습니다.
값이 뒤에서 부터 1byte 씩 잘려서 나왔다는 것 역시 확인할 수 있습니다.

Byte Ordering

여기서 다시 한번 짚고 넘어가야 할 정보 중 하나는 byte ordering 에 관한 문제입니다.

  • 리틀 엔디안 (Little Endian) 은 낮은 차수의 숫자가 낮은 주소에
  • 빅 엔디안 Big Endian)은 높은 차수의 숫자가 낮은 주소에

물론 둘 다 1byte 내부에 기록된 내용은 같습니다. byte ordering 은 byte 간의 순서를 결정 짓습니다.

얼마만큼 묶어서 읽어 들일지에 따라서 그 값이 달라질 수 있습니다.
int 형은 4byte 를 한번에 묶어서 읽어들입니다. 주로 사용하는 x86명령어 집합은 little Endian 방식이므로, 낮은 차수의 숫자가 낮은 주소에 위치하게 됩니다.

  • 메모리는 낮은 주소에서 높은 주소로 향합니다.
  • 예를 들어, 시작점이 0x0010이라고 한다면 0x0010부터 0x0013까지 위치합니다.

그렇다면 0x10203040은 각각 아래 처럼 보관됩니다.

  • 0x0010에 40
  • 0x0011에 30
  • 0x0012에 20
  • 0x0013에 10

CharValue 는 0x0010을 가르키고 있으며, 인덱스 연산자의 순서대로 0x0010, 0x0011, 0x0012, 0x0013을 차례대로 가르킵니다. 따라서 바이트 순서가 뒤집어진 형태가 나오게 됩니다.

이름 없는 union

위의 소스 코드중 main 함수에 이름이 없는 union 선언이 있습니다.
이 선언법은 마찬가지로 해당하는 멤버들을 union 으로써 만들어 내지만, 별도의 자료형으로 정의하지는 않습니다.

union 
{
    int IntValue;
    char ByteValue[4];
    short WordValue[2];
};

IntValue, ByteValue, WordValue 이라는 변수가 union 이라는 것을 명시해 주는 것입니다.
short 는 2byte 의 자료형입니다. Word 는 2byte 자료형을 표현할때 사용하기도 하는 단위입니다.

IntValue 에 0x40302010을 넣으면, Word 는 2byte 씩 묶어서 읽어들이기 때문에 쪼개어서 읽었을 때 2byte 단위로 순서가 바뀌는 것을 확인할 수 있습니다.

이 블로그는 개인 블로그입니다. 게시글은 오류를 포함하고 있을 수 있지만, 저자는 오류를 해결하기 위해 노력하고 있습니다.
게시글에 별도의 고지가 없는 경우, 크리에이티브 커먼즈 저작자표시-비영리-변경금지 4.0 라이선스를 따릅니다.

This blog is personal blog. published posts may contain some errors, but author doing efforts to clear errors.
If post have not notice of license, it under creative commons Attribution-NonCommercial-NoDerivatives 4.0.