본문 바로가기
프로그래밍/C, C++

C 언어의 구조체

by argentdarae 2025. 4. 9.
반응형

구조체란 여러 자료형을 가진 변수들을 하나의 패키지로 묶은 데이터의 집합이다

 

구조체의 장점

  • 비슷한 데이터를 모아 코드를 빠르게 이해할 수 있다
  • 매직 넘버를 방지하여 실수를 줄일 수 있다
  • 원자성을 보장하는 연산을 통해 실수를 방지할 수 있다

 

구조체의 선언 및 사용

구조체는 지역변수로 선언 시 초기화되지 않으므로 명시적으로 초기화해줘야 한다. 전역변수로 선언시 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

Are there any downsides to passing structs by value in C, rather than passing a pointer? - 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