반응형
구조체란 여러 자료형을 가진 변수들을 하나의 패키지로 묶은 데이터의 집합이다
구조체의 장점
- 비슷한 데이터를 모아 코드를 빠르게 이해할 수 있다
- 매직 넘버를 방지하여 실수를 줄일 수 있다
- 원자성을 보장하는 연산을 통해 실수를 방지할 수 있다
구조체의 선언 및 사용
구조체는 지역변수로 선언 시 초기화되지 않으므로 명시적으로 초기화해줘야 한다. 전역변수로 선언시 BSS 영역에 의해 초기화 되지만, 함수 내에서 지역변수로 선언되면 메모리에 남아있는 쓰레기 값이 들어가기 때문이다
#include <stdio.h>
struct MyData {
int x;
double y;
};
/* 전역 변수: BSS 영역에 의해 자동으로 0으로 초기화됨 */
struct MyData globalData;
int main(void)
{
/* 지역 변수: 명시적으로 초기화해주지 않으면 쓰레기 값이 들어갈 수 있음 */
struct MyData localData;
printf("Global data => x: %d, y: %f\n", globalData.x, globalData.y);
printf("Local data => x: %d, y: %f\n", localData.x, localData.y);
return 0;
}
================ 실행 결과 ================
Global data => x: 0, y: 0.000000
Local data => x: -2042741660, y: 0.000000
typedef의 활용
typedef는 기존 자료형에 별명을 붙이는 기능이다. 구조체에 typedef를 사용하면 코드를 간결하게 작성할 수 있다
typedef를 사용할 땐 접미사로 _t를 붙이며, enum에도 typedef를 사용할 수 있다
#include <stdio.h>
/* typedef를 사용해 구조체에 별명을 붙임 */
typedef struct MyData {
int x;
double y;
} MyData_t;
/* 전역 변수: BSS 영역에 의해 자동으로 0으로 초기화됨 */
MyData_t globalData;
int main(void)
{
/* 지역 변수: 명시적으로 초기화해주지 않으면 쓰레기 값이 들어갈 수 있음 */
MyData_t localData;
/* 전역 변수는 0으로 초기화되어 있음 */
printf("Global data => x: %d, y: %f\n", globalData.x, globalData.y);
/* 지역 변수는 쓰레기 값이 들어갈 수 있음 */
printf("Local data => x: %d, y: %f\n", localData.x, localData.y);
return 0;
}
================ 실행 결과 ================
Global data => x: 0, y: 0.000000
Local data => x: -2042741660, y: 0.000000
함수와 구조체
구조체는 기본 자료형과 동일하게 값으로 전달되어, 모든 데이터가 복사되어 넘어간다. 따라서 구조체 데이터가 클 경우 불필요한 연산이 있을 수 있다
만약 원본만을 수정하고 싶다면 포인터를 통해 주소를 전달해야 한다
반환값도 마찬가지이다
#include <stdio.h>
/* 구조체를 typedef로 간단하게 정의 */
typedef struct MyData {
int x;
double y;
} MyData_t;
/* 1) 구조체를 값으로 전달하는 함수 */
void updateDataValue(MyData_t data)
{
data.x = 100;
data.y = 200.0;
/* 여기서 data는 함수 스택 영역에 복사된 값이므로,
함수를 빠져나가면 원본에는 영향이 없음 */
}
/* 2) 구조체 포인터(주소)를 전달하는 함수 */
void updateDataPointer(MyData_t *pData)
{
pData->x = 100;
pData->y = 200.0;
/* pData가 가리키는 실제 메모리를 수정하므로 원본이 바뀜 */
}
/* 3) 구조체를 반환하는 함수 (복사에 의한 반환) */
MyData_t createData(int x, double y)
{
MyData_t temp;
temp.x = x;
temp.y = y;
return temp;
/* 함수가 끝날 때 구조체 temp가 복사되어 반환됨 */
}
int main(void)
{
/* 예시 1: 값으로 전달 */
MyData_t data1 = {10, 20.0};
printf("[초기 data1] x = %d, y = %f\n", data1.x, data1.y);
updateDataValue(data1); /* 복사본만 수정, 원본은 변경 X */
printf("[값으로 전달 후 data1] x = %d, y = %f\n", data1.x, data1.y);
/* 예시 2: 포인터로 전달 */
MyData_t data2 = {10, 20.0};
printf("[초기 data2] x = %d, y = %f\n", data2.x, data2.y);
updateDataPointer(&data2); /* 실제 메모리 수정, 원본 변경 */
printf("[포인터로 전달 후 data2] x = %d, y = %f\n", data2.x, data2.y);
/* 예시 3: 구조체 반환 */
MyData_t data3;
data3 = createData(55, 66.6); /* createData() 내부에서 만들어진 구조체 복사 */
printf("[함수 반환으로 얻은 data3] x = %d, y = %f\n", data3.x, data3.y);
return 0;
}
================ 실행 결과 ================
[초기 data1] x = 10, y = 20.000000
[값으로 전달 후 data1] x = 10, y = 20.000000
[초기 data2] x = 10, y = 20.000000
[포인터로 전달 후 data2] x = 100, y = 200.000000
[함수 반환으로 얻은 data3] x = 55, y = 66.600000
Reference
struct (C programming language) - Wikipedia
Why should we typedef a struct so often in C? - stackoverflow
'프로그래밍 > C, C++' 카테고리의 다른 글
C 구조체와 비트 플래그 (0) | 2025.04.10 |
---|---|
C 구조체 사용 시 포인터 저장 문제 (0) | 2025.04.09 |
C 언어 파일 탐색 (0) | 2025.04.09 |
C의 파일 오류 처리 (0) | 2025.04.09 |
C 언어 파일 입출력 (0) | 2025.04.09 |