Quick Reference
구조체는 함께 움직이는 필드를 하나의 데이터 계약으로 묶습니다. 필드가 값인지 포인터인지에 따라 복사와 해제 책임이 달라지는 점이 핵심입니다.
#include <stdio.h>
typedef struct {
char name[32];
int age;
double score;
} Student;
Student student = {"Mina", 20, 97.5};
printf("%s %d %.1f\n", student.name, student.age, student.score);Student copy = student; /* 배열·숫자 필드는 값으로 복사 */
copy.score = 100.0;필드가 전부 값이면 =로 구조체를 복사할 수 있습니다. 구조체 안의 포인터는 주소만 복사하므로, 독립 소유가 필요하면 새 저장 공간과 복사·해제 규칙을 따로 만듭니다.
선언과 전달
typedef는 타입 별칭일 뿐 새 런타임 동작을 만들지 않습니다. Student처럼 함께 전달되는 데이터에 이름을 붙이고, 읽기만 하는 함수에는 const Student *, 수정하는 함수에는 Student *를 사용합니다.
#include <stdio.h>
void print_student(const Student *student) {
if (student != NULL) {
printf("%s: %.1f\n", student->name, student->score);
}
}
void reset_score(Student *student) {
student->score = 0.0;
}작은 구조체는 값으로 넘겨도 읽기 쉽지만, 큰 구조체나 원본 수정이 필요한 경우에는 포인터 전달이 자연스럽습니다. 포인터를 받는 함수는 NULL을 허용하는지 계약으로 정합니다.
값 복사와 소유권
포인터 필드가 없는 구조체는 =로 복사하면 각 필드 값이 독립적으로 복사됩니다.
typedef struct {
int x;
int y;
} Point;
Point a = {10, 20};
Point b = a;반대로 포인터 필드는 주소만 복사됩니다. 독립 소유가 필요하다면 메모리를 새로 할당하고 문자열 내용을 복사하는 생성·해제 쌍을 둡니다. 아래 생성 함수는 Person person = {0};처럼 NULL로 초기화한 객체만 받습니다.
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char *name;
} Person;
bool person_init(Person *person, const char *name) {
if (person == NULL || person->name != NULL || name == NULL) {
return false;
}
size_t length = strlen(name);
char *copy = malloc(length + 1);
if (copy == NULL) {
return false;
}
memcpy(copy, name, length + 1);
person->name = copy;
return true;
}
void person_destroy(Person *person) {
if (person != NULL) {
free(person->name);
person->name = NULL;
}
}Person b = a;는 name 포인터만 복사하는 얕은 복사입니다. a와 b가 같은 문자열을 해제하면 double free가 되고, 한쪽을 먼저 해제하면 다른 쪽은 dangling pointer를 갖습니다. POSIX 프로젝트의 strdup도 같은 소유권 책임을 만들며, ISO C만 사용하는 코드에서는 위처럼 표준 함수로 명시합니다.
주의할 점
- 구조체의 값 복사는 포인터 필드까지 깊게 복사하지 않습니다.
- 포인터 필드가 있으면 누가 할당하고, 누가 해제하며, 복사는 독립 소유인지 공유인지 계약으로 정합니다.
- 구조체 포인터 필드 접근은
->를 사용합니다. .와 ->의 자세한 문법은 구조체 포인터 카드에서 이어서 확인합니다. - 구조체의 메모리 배치는 padding을 포함할 수 있으므로, 구조체 전체를 파일·네트워크로 그대로 쓰는 직렬화 도구로 보지 않습니다.
참고 링크
3 sources