핵심 정리

공용체

공용체는 union 키워드로 정의하며 멤버 중에서 가장 큰 자료형의 공간을 공유합니다.

// 공용체 정의하기
union 공용체이름 {
    자료형 멤버이름;
};

// 공용체 변수 선언하기
union 공용체이름 변수이름;

// 공용체를 정의하는 동시에 변수 선언하기
union 공용체이름 {
    자료형 멤버이름;
} 변수;

// 공용체를 정의하면서 공용체 별칭 정의하기
typedef union 공용체이름 {
    자료형 멤버이름;
} 공용체별칭;

// 익명 공용체 정의하기
typedef union {
    자료형 멤버이름;
} 공용체별칭;

// 공용체 별칭으로 변수 선언하기
공용체별칭 변수이름;

다음 공용체는 가장 큰 자료형인 int의 공간을 공유하며 공용체의 크기는 int의 크기와 같습니다.

union A {
    int x;     // 가장 큰 자료형인 int의 공간을 공유함
    char y;
    short z;
};

공용체 멤버에 접근할 때는 .(점)을 사용합니다.

union 공용체이름 변수이름;

변수.멤버;         // 공용체 멤버의 값을 가져옴
변수.멤버 = ;    // 공용체 멤버에 값을 저장

malloc 함수로 공용체 포인터에 메모리를 할당할 수 있으며 이때는 멤버에 접근할 때 -> (화살표 연산자)를 사용합니다.

// 공용체 포인터에 동적 메모리 할당
struct 공용체이름 *포인터이름 = malloc(sizeof(union 공용체이름));

// 공용체 별칭으로 포인터를 선언하고 동적 메모리 할당
공용체별칭 *포인터이름 = malloc(sizeof(공용체별칭));

포인터->멤버;         // 공용체 포인터 멤버의 값을 가져옴
포인터->멤버 = ;    // 공용체 포인터 멤버에 값을 저장

free(포인터);    // 공용체 메모리 해제

공용체도 포인터에 공용체 변수의 메모리 주소를 구해서 할당할 수 있습니다. 또한, 공용체도 배열 및 배열 포인터로 만들 수 있고, memset, memcpy 함수를 사용할 수 있으며 방식은 구조체와 같습니다.

구조체와 공용체 함께 사용하기

구조체 안에 구조체를 멤버로 넣을 수 있으며 구조체와 공용체는 섞어서 쓸 수 있습니다.

struct 구조체A {
    자료형 멤버이름;
};

struct 구조체B {
    자료형 멤버이름
    struct 구조체A 멤버이름;    // 구조체A를 멤버로 가짐
};

struct 구조체B 변수이름;

변수.멤버.멤버          // 구조체 안의 구조체 멤버 값을 가져옴
변수.멤버.멤버 = ;    // 구조체 안의 구조체 멤버에 값을 저장

구조체 포인터의 멤버는 -> 연산자로 접근하고, 변수는 .을 사용하여 순차적으로 접근합니다.

struct 구조체B *포인터이름 = malloc(sizeof(struct 구조체B));

포인터->멤버.멤버;         // 구조체 포인터의 구조체에서 멤버 값을 가져옴
포인터->멤버.멤버 = ;    // 구조체 포인터의 구조체에서 멤버에 값을 저장

free(포인터);    // 구조체 메모리 해제

구조체는 공용체를 멤버로 가질 수 있습니다.

union 공용체C {
    자료형 멤버이름;
};

// 구조체와 공용체를 섞어서 사용
struct 구조체C {
    자료형 멤버이름;
    union 공용체C 멤버이름;    // 공용체A를 멤버로 가짐
};

변수.멤버.멤버;         // 구조체 안의 공용체 멤버 값을 가져옴
변수.멤버.멤버 = ;    // 구조체 안의 공용체 멤버에 값을 저장

구조체 안에 다른 구조체의 포인터를 멤버로 가지고 있다면 바깥 구조체 포인터에 메모리를 먼저 할당한 뒤 멤버에 메모리를 할당합니다. 메모리를 해제할 때는 반대로 멤버를 먼저 해제한 뒤 바깥 구조체를 해제합니다.

struct 구조체A {
    자료형 멤버이름;
};

struct 구조체B {
    자료형 멤버이름;
    struct 구조체A *멤버이름;    // 구조체A의 포인터를 멤버로 가짐
};

struct 구조체B *포인터이름 = malloc(sizeof(struct 구조체B));   // 바깥 구조체의 포인터에 메모리 할당
포인터->구조체A포인터 = malloc(sizeof(struct 구조체A));        // 멤버 포인터에 메모리 할당

변수->멤버->멤버;         // 구조체 포인터의 구조체 포인터에서 멤버 값을 가져옴
변수->멤버->멤버 = ;    // 구조체 포인터의 구조체 포인터에서 멤버에 값을 저장

free(포인터->구조체A포인터);    // 구조체 멤버의 메모리를 먼저 해제
free(포인터);                  // 구조체 메모리 해제

익명 구조체와 익명 공용체를 함께 사용하면 같은 값이지만 이름과 형태를 달리하여 접근할 수 있습니다.

struct 구조체이름 {
    union {              // 익명 공용체
        struct {             // 익명 구조체
            자료형 멤버이름A;     // 변수로 접근할 때 사용
            자료형 멤버이름B;
            자료형 멤버이름C;
        };
        자료형 배열이름[3];   // 배열로 접근할 때 사용
    };
};

struct 구조체이름 변수이름;

변수.멤버A;       // 같은 값을 변수로 접근
변수.배열[0];     // 같은 값을 배열의 인덱스로 접근