65.2 구조체 포인터 매개변수 사용하기

이번에는 구조체 포인터를 매개변수로 사용해보겠습니다. 다음과 같이 ( ) (괄호) 안에서 구조체 이름 뒤에 * (애스터리스크)를 붙여서 매개변수를 포인터 형태로 만듭니다.

반환값자료형 함수이름(struct 구조체이름 *매개변수)
{
}

다음 내용을 소스 코드 편집 창에 입력한 뒤 실행해보세요.

parameter_struct_pointer_set_value.c

#define _CRT_SECURE_NO_WARNINGS    // strcpy 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h>    // strcpy 함수가 선언된 헤더 파일

struct Person {
    char name[20];
    int age;
    char address[100];
};

void setPerson(struct Person *p)    // 반환값 없음, 구조체 포인터 매개변수 한 개 지정
{
    // 매개변수로 받은 포인터에서 구조체 멤버의 값 변경
    strcpy(p->name, "고길동");
    p->age = 40;
    strcpy(p->address, "서울시 서초구 반포동");
}

int main()
{
    struct Person p1;

    strcpy(p1.name, "홍길동");
    p1.age = 30;
    strcpy(p1.address, "서울시 용산구 한남동");

    setPerson(&p1);    // 함수를 호출할 때 구조체 변수의 메모리 주소를 전달

    // setPerson에서 변경한 값이 출력됨
    printf("이름: %s\n", p1.name);       // 이름: 고길동
    printf("나이: %d\n", p1.age);        // 나이: 40
    printf("주소: %s\n", p1.address);    // 주소: 서울시 서초구 반포동

    return 0;
}

실행 결과

이름: 고길동
나이: 40
주소: 서울시 서초구 반포동

함수를 만들 때 void setPerson(struct Person *p)와 같이 매개변수를 구조체 포인터로 지정했습니다. 그리고 함수 안에서 포인터로 받은 구조체 멤버의 값을 변경합니다.

void setPerson(struct Person *p)    // 반환값 없음, 구조체 포인터 매개변수 한 개 지정
{
    // 매개변수로 받은 포인터에서 구조체 멤버의 값 변경
    strcpy(p->name, "고길동");
    p->age = 40;
    strcpy(p->address, "서울시 서초구 반포동");
}

구조체 변수 p1을 선언하고 각 멤버에 "홍길동", 30, "서울시 용산구 한남동"을 저장했습니다. 함수 setPerson은 매개변수가 구조체 포인터이므로 & (주소 연산자)를 사용하여 p1의 주소를 전달해야 합니다.

struct Person p1;

strcpy(p1.name, "홍길동");
p1.age = 30;
strcpy(p1.address, "서울시 용산구 한남동");

setPerson(&p1);    // 함수를 호출할 때 구조체 변수의 메모리 주소를 전달

printf로 구조체 멤버의 값을 출력해보면 함수 setPerson에서 변경한 값인 "고길동", 40, "서울시 서초구 반포동"이 출력됩니다. 즉, 매개변수를 구조체 포인터로 사용하면 구조체 멤버의 값이 복사되지 않고 메모리 주소만 전달됩니다. 결국, 함수 setPerson에서는 바깥에 선언된 구조체 변수의 값을 변경하게 되죠.

// setPerson에서 변경한 값이 출력됨
printf("이름: %s\n", p1.name);       // 이름: 고길동
printf("나이: %d\n", p1.age);        // 나이: 40
printf("주소: %s\n", p1.address);    // 주소: 서울시 서초구 반포동
참고 | 복합 리터럴 사용하기(구조체 포인터)

함수에 구조체 포인터를 넘겨줄 때 복합 리터럴을 사용하려면 리터럴 앞에 &를 붙이면 됩니다.

  • &(struct 구조체이름) { .멤버이름 = 값1, .멤버이름2 = 값2 }
  • &(struct 구조체이름) { 값1, 값2 }

compound_literal_struct_pointer.c

#include <stdio.h>

struct Person {
    char name[20];
    int age;
    char address[100];
};

void printPerson(struct Person *p)
{
    printf("이름: %s\n", p->name);
    printf("나이: %d\n", p->age);
    printf("주소: %s\n", p->address);
}

int main()
{
    // 복합 리터럴 방식으로 구조체를 넘겨줌
    printPerson(&(struct Person) { .name = "홍길동", .age = 30, .address = "서울시 용산구 한남동" });

    // 복합 리터럴 방식으로 구조체를 넘겨줌. 멤버 이름 생략
    printPerson(&(struct Person) { "고길동", 40, "서울시 서초구 반포동" });

    return 0;
}
참고 | 구조체 별칭 사용하기

구조체 포인터 별칭을 정의했다면 함수의 매개변수에 구조체 포인터 별칭을 그대로 지정해주면 됩니다(물론 구조체 별칭도 매개변수로 지정할 수 있습니다).

parameter_typedef_struct.c

typedef struct _Person {
    char name[20];
    int age;
    char address[100];
} Person, *PPerson;    // 구조체 별칭 Person, 구조체 포인터 별칭 PPerson

void setPerson(PPerson p)    // Person 구조체 포인터의 별칭을 매개변수로 지정
{
    strcpy(p->name, "고길동");
    p->age = 40;
    strcpy(p->address, "서울시 서초구 반포동");
}
참고 | 공용체와 열거형을 매개변수로 사용하기

다음과 같이 함수에서 공용체와 열거형도 매개변수로 사용할 수 있습니다.

parameter_union_enum.c

#include <stdio.h>

union Box {
    short candy;
    float snack;
    char doll[8];
};

enum BOX_TYPE {
    BOX_PAPER = 0,
    BOX_WOOD,
    BOX_PLASTIC
};

void printBox(union Box box)    // 반환값 없음, 공용체 매개변수 한 개 지정
{
    printf("%d\n", box.candy);
}

void printBoxType(enum BOX_TYPE boxType)   // 반환값 없음, 열거형 매개변수 한 개 지정
{
    printf("%d\n", boxType);
}

int main()
{
    union Box box;
    enum BOX_TYPE boxType;

    box.candy = 10;
    boxType = BOX_PLASTIC;

    printBox(box);            // 10: 함수를 호출할 때 공용체 변수 전달
    printBoxType(boxType);    //  2: 함수를 호출할 때 열거형 값 전달

    return 0;
}

지금까지 함수에서 구조체 매개변수를 사용하는 방법을 배웠습니다. 실제로 프로그래밍을 하다보면 구조체 또는 구조체 포인터를 주고 받는 경우가 많으므로 이 부분은 정확히 익히는 것이 중요합니다. 특히 문법이 약간 복잡하므로 반복 학습하는 것이 좋습니다.