C언어 중첩 구조체와 포인터 접근
선수학습(2개)
요약
C언어 중첩 구조체(구조체 안의 구조체)의 선언·초기화·포인터 접근(p->outer.inner.field)을 다단계로 추적하는 방법을 정리합니다. 정보처리기사 실기 대비 심화 주제로, ->와 .의 차이를 메모리 다이어그램으로 익힙니다.
아래에서 하나씩 배울 내용을 미리 정리한 표입니다.
| 개념 | 설명 | 예시 |
|---|---|---|
| 중첩 구조체 | 구조체를 다른 구조체의 멤버로 포함 | struct Student { struct Date birth; }; |
| 중첩 초기화 | 중괄호를 안쪽까지 한 번 더 묶어 초기화 | {1001, {2025, 3, 19}} |
| 포인터 + . 접근 | ->로 한 번 풀고 이후는 .으로 이어감 | p->birth.year |
| 3단 이상 중첩 | .을 계속 이어 붙이면 됨 | p->info.birth.year |
중첩 구조체란? 기초
구조체의 멤버는 int, char, 배열뿐 아니라 다른 구조체도 될 수 있습니다. 이렇게 구조체가 구조체를 품은 형태를 중첩 구조체라고 합니다. 학생 정보에 생년월일(year, month, day)을 같이 담거나, 주소 정보에 도시와 우편번호를 하나로 묶는 것처럼, 하나의 개념 안에 세부 필드가 다시 묶일 때 사용합니다.

Student 박스 안에 id(int)와 함께 birth라는 또 하나의 **박스(Date 구조체)**가 통째로 들어 있는 모양입니다. birth는 단일 값이 아니라 year, month, day 3개의 필드를 안에 품은 구조체입니다.
중첩 구조체 변수를 초기화할 때는 중괄호를 안쪽까지 한 번 더 묶어 작성합니다.
바깥 {}는 Student를, 안쪽 {2025, 3, 19}는 birth 멤버(Date)를 채웁니다. Date의 멤버 순서(year, month, day)에 맞춰 값이 들어갑니다.
포인터로 중첩 구조체 접근 심화
구조체 포인터로 중첩 구조체의 멤버에 접근하려면 ->와 .을 섞어서 씁니다.
포인터 단계는 처음 한 번만 ->를 쓰고, 이후 구조체 멤버를 따라갈 때는 전부 .입니다. 연결리스트에서 본 head->n2->n1처럼 ->가 두 번 연속된 것은 n2가 포인터 멤버였기 때문입니다. 반면 아래 예제의 birth는 구조체 값 멤버이므로, 포인터가 아니라 .으로 이어야 합니다.

핵심은 점프(->)는 포인터를 만났을 때만, 같은 박스 안의 멤버에는 . 라는 원칙입니다.
예제: 학생 + 생년월일
출력: 2025/3/19
단계별로 풀어서 해석하기
s가 주소 100에 있고, 포인터 p가 주소 1000에 있다고 가정합니다.
p->birth.year를 왼쪽부터 한 단계씩 풀어봅시다.
핵심은 p->birth가 반환하는 것이 구조체(값)이지 포인터가 아니라는 점입니다. 그래서 그 다음 단계는 .으로 이어야 합니다.
초기화 {2025, 3, 19}의 순서는 Date의 멤버 순서(year, month, day)와 일치하므로 year=2025, month=3, day=19가 각각 들어갑니다. 같은 1단계/2단계 방식으로 추적하면 p->birth.month는 3, p->birth.day는 19입니다.

3단 이상 깊은 중첩 심화
구조체가 또 다른 구조체를 품으면 .을 이어 붙이기만 하면 됩니다. 아래는 Student → Info → Date 순으로 3단 중첩된 예제입니다.
초기화 {2001, {{2005, 6, 15}, 3}}에서 바깥 {}는 Student, 그 안의 {}는 Info, 가장 안쪽 {2005, 6, 15}는 Date를 채웁니다.
p->info.birth.year를 단계별로 추적하면 이렇습니다.

p에서 포인터를 한 번 풀어낸 뒤로는, 구조체 멤버를 따라가는 동안 .만 사용한다는 원칙은 동일합니다.