55 구조체와 공용체 활용하기

지금까지 구조체와 공용체를 단독으로 사용했습니다. 하지만 구조체 안에 구조체와 공용체가 들어갈 수 있고, 반대로 공용체 안에 구조체와 공용체가 들어갈 수도 있습니다. 이번에는 구조체와 공용체를 조합하는 방법을 알아보겠습니다.

55.1 구조체 안에서 구조체 멤버 사용하기

다음과 같이 구조체는 구조체를 멤버로 가질 수 있습니다.

struct_variable_in_struct.c

#include <stdio.h>

struct Phone {    // 휴대전화 구조체
    int areacode;                 // 국가번호
    unsigned long long number;    // 휴대전화 번호
};

struct Person {    // 사람 구조체
    char name[20];         // 이름
    int age;               // 나이
    struct Phone phone;    // 휴대전화. 구조체를 멤버로 가짐
};

int main()
{
    struct Person p1;

    p1.phone.areacode = 82;          // 변수.멤버.멤버 순으로 접근하여 값 할당
    p1.phone.number = 3045671234;    // 변수.멤버.멤버 순으로 접근하여 값 할당

    printf("%d %llu\n", p1.phone.areacode, p1.phone.number);    // 82 3045671234

    return 0;
}

실행 결과

82 3045671234

구조체를 멤버로 가지려면 다음과 같이 구조체 안에서 구조체 변수를 선언하면 됩니다. 여기서는 사람 구조체가 휴대전화 구조체를 멤버로 가지고 있습니다.

struct Person {    // 사람 구조체
    char name[20];         // 이름
    int age;               // 나이
    struct Phone phone;    // 휴대전화. 구조체를 멤버로 가짐
};

멤버에 접근할 때는 . (점)을 사용하며 가지고 있는 구조체에 계층적으로 접근하면 됩니다. 다음은 점을 두 번 사용하여 휴대전화 구조체의 areacodenumber 멤버에 접근하여 값을 할당하고, 값을 가져옵니다.

  • 변수.멤버.멤버
p1.phone.areacode = 82;          // 변수.멤버.멤버 순으로 접근하여 값 할당
p1.phone.number = 3045671234;    // 변수.멤버.멤버 순으로 접근하여 값 할당

printf("%d %llu\n", p1.phone.areacode, p1.phone.number);    // 82 31045671234
참고 | 구조체 정의 순서

구조체를 Phone → Person 순서가 아니라 PersonPhone 순서로 정의하면 문제가 없을까요? 실제로 순서를 바꿔서 컴파일 해보면 정의되지 않는 구조체를 사용한다는 식으로 에러 메시지가 나옵니다. 구조체 안에 구조체가 변수로 들어갈 때는 안에 들어가는 구조체를 먼저 선언해줍니다.

만약 Phone 구조체를 다른 곳에서는 쓰지 않고 특정 구조체 안에서만 쓴다면 구조체 안에 구조체를 정의하는 게 더 편리합니다. 단, 이때는 구조체를 정의한 뒤 반드시 변수를 선언해야 합니다.

struct Person {    // 사람 구조체
    char name[20];    // 이름
    int age;          // 나이
    struct Phone {    // 휴대전화 구조체를 사람 구조체 안에 정의
        int areacode;                 // 국가번호
        unsigned long long number;    // 휴대전화 번호
    } phone;                          // 구조체를 정의하는 동시에 변수 선언
};
참고 | 국제전화 국가번호

국제전화에서 82는 대한민국 국가코드입니다. 그리고 국가코드와 휴대전화 번호를 함께 적으려면 010에서 맨 앞의 0은 빼고 +82-10-0000-0000와 같이 적으면 됩니다. 보통 프로그램에서는 +와 -를 빼고 저장하며 사람에게 보여줄 때 +와 -를 붙입니다.

예제에서는 국가코드와 전화번호를 정수로 저장했지만 보통 전화번호는 연산을 하지 않는 대신 검색을 하므로 문자열에 저장해도 됩니다(주로 데이터베이스에 저장한 뒤 꺼내 쓰지요).

참고 | 구조체 변수를 선언하는 동시에 초기화하기

구조체 변수를 선언하면서 안에 들어있는 구조체까지 초기화하려면 { } (중괄호) 안에 중괄호를 사용합니다.

  • struct 구조체이름 변수이름 = { 값1, 값2, { 값3, 값4 } };

다음과 같이 구조체 안에 들어있는 구조체 멤버 위치에 중괄호를 사용하여 값을 묶어주면 됩니다.

struct_variable_in_struct_init.c

#include <stdio.h>

struct Phone {
    int areacode;
    unsigned long long number;
};

struct Person {
    char name[20];
    int age;
    struct Phone phone;
};

int main()
{
    // phone의 멤버 areacode에는 82, number에는 3045671234
    struct Person p1 = { .name = "Andrew", .age = 25, { .areacode = 82, .number = 3045671234 } };

    printf("%d %llu\n", p1.phone.areacode, p1.phone.number);    // 82 3045671234

    // phone의 멤버 areacode에는 82, number에는 3087654321
    struct Person p2 = { "Maria", 19, { 82, 3087654321 } };

    printf("%d %llu\n", p2.phone.areacode, p2.phone.number);    // 82 3087654321

    return 0;
}