Skip to content

58. 함수 구조체 매개변수


1. 키워드

  • 구조체 매개변수


2. 함수에서 구조체 매개변수 사용하기

  • 함수에 전달해야 할 매개변수가 이름, 나이, 전화번호, 우편번호, 주소처럼 많을 때 다음과 같이 작성할 수 있다.


void printPerson(char *name, int age, long long phoneNumber, int postalCode, char *address)


  • 하지만 이렇게 작성하면 코드도 길어지고 너무 복잡해진다.
  • 이럴 때는 관련 정보를 구조체로 묶어서 매개변수로 전달하면 간단해진다.


void printPerson(struct Person p)


3. 구조체 매개변수 사용하기

  • 함수에서 구조체를 매개변수로 사용하려면 ()(괄호) 안에서 struct 키워드와 구조체 이름으로 매개변수를 지정해 준다.


반환값자료형 함수이름(struct 구조체이름 매개변수)
{
}
#define _CRT_SECURE_NO_WARNINGS // strcpy 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h> // strcpy 함수가 선언된 헤더 파일

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()
{
    struct Person p1;

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

    printPerson(p1); // 함수를 호출할 때 구조체 변수 전달, 멤버가 복사됨

    return 0;
}

// 이름: 홍길동
// 나이: 30
// 주소: 서울시 용산구 한남동


  • 함수를 작성할 때 void printPerson(struct Person p)와 같이 구조체를 매개변수로 지정했다.
  • 그리고 함수 안에서는 구조체 매개변수 멤버의 값을 출력한다.


void printPerson(struct Person p) // 반환값 없음, 구조체 매개변수 한 개 지정
{
    // 구조체 매개변수 멤버의 값 출력
    printf("이름: %s\n", p.name);
    printf("나이: %d\n", p.age);
    printf("주소: %s\n", p.address);
}


  • 함수를 호출할 때 구조체 변수를 넣어주면 구조체 변수의 모든 멤버가 매개변수로 복사된다.
  • 단, 구조체 크기가 커지면 복사할 공간이 그만큼 더 필요하게 되므로 공간이 낭비되어 비효율적이다.
  • 보통 매개변수로 구조체를 전달할 때는 포인터를 활용하는 것이 좋다.


int main()
{
    struct Person p1;

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

    printPerson(p1); // 함수를 호출할 때 구조체 변수 전달, 멤버가 복사됨

    return 0;
}


복합 리터럴 사용하기(구조체)

  • 함수에 구조체를 넘겨줄 때 복합 리터럴을 사용하면 구조체 변수를 따로 선언하지 않아도 된다.


(struct 구조체이름) { .멤버이름 = 값1, .멤버이름2 = 값2 }
(struct 구조체이름) { 값1, 값2 }
#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;
}

// 이름: 홍길동
// 나이: 30
// 주소: 서울시 용산구 한남동
// 이름: 고길동
// 나이: 40
// 주소: 서울시 서초구 반포동


  • 다음과 같이 함수 안에서 매개변수로 받은 구조체 멤버의 값을 변경해도 함수 바깥에는 영향을 미치지 않는다.


#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);

    printf("이름: %s\n", p1.name);
    printf("나이: %d\n", p1.age);
    printf("주소: %s\n", p1.address);

    return 0;
}

// 이름: 홍길동
// 나이: 30
// 주소: 서울시 용산구 한남동


  • 매개변수로 값이 전달될 때 구조체 멤버가 모두 복사되었으므로 구조체 멤버를 아무리 변경해 봐야 바깥에 있는 구조체 변수에는 영향을 미치지 않는다.


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

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


반환값자료형 함수이름(struct 구조체이름 *매개변수)
{
}
#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);
    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);
printf("주소: %s\n", p1.address);


복합 리터럴 사용하기(구조체 포인터)

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


&(struct 구조체이름) { .멤버이름 = 값1, .멤버이름2 = 값2 }
&(struct 구조체이름) { 값1, 값2 }
#define _CRT_SECURE_NO_WARNINGS // strcpy 보안 경고로 인한 컴파일 에러 방지
#include <stdio.h>
#include <string.h> // strcpy 함수가 선언된 헤더 파일

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;
}

// 이름: 홍길동
// 나이: 30
// 주소: 서울시 용산구 한남동
// 이름: 고길동
// 나이: 40
// 주소: 서울시 서초구 반포동


구조체 별칭 사용하기

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


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, "서울시 서초구 반포동");
}


공용체와 열거형을 매개변수로 사용하기

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


#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);         // 함수를 호출할 때 공용체 변수 전달
    printBoxType(boxType); // 함수를 호출할 때 열거형 값 전달

    return 0;
}

// 10
// 2

References