58. 함수 구조체 매개변수
1. 키워드
- 구조체 매개변수
2. 함수에서 구조체 매개변수 사용하기
- 함수에 전달해야 할 매개변수가 이름, 나이, 전화번호, 우편번호, 주소처럼 많을 때 다음과 같이 작성할 수 있다.
- 하지만 이렇게 작성하면 코드도 길어지고 너무 복잡해진다.
- 이럴 때는 관련 정보를 구조체로 묶어서 매개변수로 전달하면 간단해진다.
3. 구조체 매개변수 사용하기
- 함수에서 구조체를 매개변수로 사용하려면
()
(괄호) 안에서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;
}
복합 리터럴 사용하기(구조체)
- 함수에 구조체를 넘겨줄 때 복합 리터럴을 사용하면 구조체 변수를 따로 선언하지 않아도 된다.
#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. 구조체 포인터 매개변수 사용하기
- 이번에는 구조체 포인터를 매개변수로 사용해 보자.
- 다음과 같이
()
안에서 구조체 이름 뒤에*
(애스터리스크)를 붙여서 매개변수를 포인터 형태로 만든다.
#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);
복합 리터럴 사용하기(구조체 포인터)
- 함수에 구조체 포인터를 넘겨줄 때 복합 리터럴을 사용하려면 리터럴 앞에
&
를 붙이면 된다.
#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
// 주소: 서울시 서초구 반포동
구조체 별칭 사용하기
- 구조체 포인터 별칭을 정의했다면 함수의 매개변수에 구조체 포인터 별칭을 그대로 지정해 주면 된다.
- 물론 구조체 별칭도 매개변수로 지정할 수 있다.
공용체와 열거형을 매개변수로 사용하기
- 다음과 같이 함수에서 공용체와 열거형도 매개변수로 사용할 수 있다.
#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