티스토리 뷰
반응형
1) 목표
▶함수 파라메타 유형에 대해서 알아보기
- call-by-value 이해하기.
- call-by-reference 이해하기.
2) 설명
- 함수에 넘겨주는 파라메타(인자값)의 유형은
값을 넘겨 주는 방식(call-by-value),
주소(포인터)를 넘겨 주는 방식(call-by-reference)이 있습니다. - call-by-value 방식은 함수를 부르는쪽이나 함수나 서로 영향을 주기 않습니다.
14.함수에서 살펴본 sum(int a, int b) 함수가 call-by-value의 전형적인 함수입니다. - call-by-reference 방식은 주소를 넘겨 주고, 넘겨 받아서 처리하기에 값에 영향을 줍니다.
3-1) call-by-value 방식 예제 프로그램
▶ vi func3.c
#include <stdio.h>
// val1값과 val2값을 바꾸는 swap함수
// call-by-value 방식
void swap_value(int val1, int val2) {
int tmp;
printf("swap_value: swap전 val1[%d][%p] val2[%d][%p]\n", val1, &val1, val2, &val2);
// tmp를 이용한 val1 <-> val2
tmp = val1;
val1 = val2;
val2 = tmp;
printf("swap_value: swap후 val1[%d][%p] val2[%d][%p]\n", val1, &val1, val2, &val2);
}
// swap함수
void main() {
int val1, val2;
val1 = 100;
val2 = 200;
printf("main: swap_value() 호출전 : val1[%d][%p] val2[%d][%p]\n", val1, &val1, val2, &val2);
// call-by-value 방식
swap_value(val1, val2);
printf("main: swap_value() 호출후 : val1[%d][%p] val2[%d][%p]\n", val1, &val1, val2, &val2);
}
▶ 컴파일/실행
~/c-lecture (master ✘)✭ ᐅ gcc -o func3 func3.c
~/c-lecture (master ✘)✭ ᐅ ./func3
main: swap_value() 호출전 : val1[100][0x7ffc1fbbb670] val2[200][0x7ffc1fbbb674]
swap_value: swap전 val1[100][0x7ffc1fbbb64c] val2[200][0x7ffc1fbbb648]
swap_value: swap후 val1[200][0x7ffc1fbbb64c] val2[100][0x7ffc1fbbb648]
main: swap_value() 호출후 : val1[100][0x7ffc1fbbb670] val2[200][0x7ffc1fbbb674]
~/c-lecture (master ✘)✭ ᐅ
▶ 분석
- swap함수내에서는 swap전, swap후의 값을 보면 val1값과 val2값이 바뀌어 있는걸 보실 수 있습니다.
그런데 main()내에서는 swap() 호출전이나 호출후의 값을 보면 그대로 인걸 알수 있습니다.
이렇듯 call-by-value방식은 호출하는쪽의 변수값을 바꾸질 못합니다.
이유는 main()함수내에서 int val1, val2; 선언시 메모리가 할당이 되고 swap_value()함수를 호출을 하면
swap_value()함수에서 파라메타에 대해서 새로운 메모리가 할당이 됩니다.
그래서 swap_value()함수내에서 작업하는 곳은 새롭게 할당된 메모리가 되어서 main()함수에서 할당받은
메모리에 여향을 주지 못합니다.
printf("main: swap_value() 호출전 : val1[%d][%p] val2[%d][%p]\n", val1, &val1, val2, &val2);
- 선언한 변수에 대해서 메모리 주소를 알아 보기 위해서 이전 강의에서 배운 %p를 사용했습니다.
또한 %p 에 대한 값으로는 변수에 대한 주소를 사용하기 위해서 변수앞에 & 를 붙여서 사용합니다.
위의 결과를 보시면 main()함수에서 val1주소, val2주소가 swap_value()함수에서는 전혀 다른 주소가 출력된걸 확인하실 수 있습니다. - main()에서 선언한 val1, val2값을 바꾸기 위해서는 어떻게 해야할까요?
해답은 이전 강의에서 배운 포인터가 사용됩니다. 알아볼까요?
3-2) call-by-reference 방식 예제 프로그램
▶ vi func4.c
#include <stdio.h>
// val1값과 val2값을 바꾸는 swap함수
// call-by-reference 방식
void swap_reference(int *pVal1, int *pVal2) {
int tmp;
printf("swap_reference: swap전 val1[%d][%p] val2[%d][%p]\n", *pVal1, pVal1, *pVal2, pVal2);
// tmp를 이용한 val1 <-> val2
tmp = *pVal1;
*pVal1 = *pVal2;
*pVal2 = tmp;
printf("swap_reference: swap후 val1[%d][%p] val2[%d][%p]\n", *pVal1, pVal1, *pVal2, pVal2);
}
// swap함수
void main() {
int val1, val2;
val1 = 100;
val2 = 200;
printf("main: swap_reference() 호출전 : val1[%d][%p] val2[%d][%p]\n", val1, &val1, val2, &val2);
// call-by-reference 방식
swap_reference(&val1, &val2);
printf("main: swap_reference() 호출후 : val1[%d][%p] val2[%d][%p]\n", val1, &val1, val2, &val2);
}
▶ 컴파일/실행
~/c-lecture (master ✘)✭ ᐅ gcc -o func4 func4.c
~/c-lecture (master ✘)✭ ᐅ ./func4
main: swap_reference() 호출전 : val1[100][0x7ffced6b8ae0] val2[200][0x7ffced6b8ae4]
swap_reference: swap전 val1[100][0x7ffced6b8ae0] val2[200][0x7ffced6b8ae4]
swap_reference: swap후 val1[200][0x7ffced6b8ae0] val2[100][0x7ffced6b8ae4]
main: swap_reference() 호출후 : val1[200][0x7ffced6b8ae0] val2[100][0x7ffced6b8ae4]
~/c-lecture (master ✘)✭ ᐅ
▶ 분석
- 실행한 결과를 보시면 main() 내 val1, val2값이 swap_reference() 호출후에 바뀌어 있는걸 확인하실 수 있습니다.
또한 main()함수내 val1, val2주소가 swap_reference()함수내에서도 같은걸 보실 수 있습니다.
이렇듯 같은 메모리 주소를 사용하므로 변수에 영향을 줄 수 있습니다.
...
// call-by-reference 방식
swap_reference(&val1, &val2);
- 함수를 호출할때 변수에 대한 주소를 넘겨주기 위해서 변수명 앞에 & 를 붙여서 넘겨 주고 있습니다.
...
// call-by-reference 방식
void swap_reference(int *pVal1, int *pVal2) {
- 호출된 함수에서도 파라메타가 주소, 즉 포인터이므로 포인터 형으로 정의가 되어 있습니다.
3-2) call-by-reference 배열 예제 프로그램
▶ vi func5.c
#include <stdio.h>
// 배열값 hello를 world로 바꾸는 함수
// call-by-reference 방식
void array_reference(char *pStr) {
char new_str[] = "world";
int i;
printf("array_reference: swap전 [%s][%p]\n", pStr, pStr);
for (i = 0; i < 6; i++) {
// new_str:world로 대체
*(pStr + i) = new_str[i];
}
printf("array_reference: swap후 [%s][%p]\n", pStr, pStr);
}
// swap함수
void main() {
char str[] = "hello";
printf("main: array_reference() 호출전 : str[%s][%p]\n", str, str);
// call-by-reference 방식
array_reference(str);
printf("main: array_reference() 호출후 : str[%s][%p]\n", str, str);
}
▶ 컴파일/실행
~/c-lecture (master ✘)✭ ᐅ gcc -o func5 func5.c
~/c-lecture (master ✘)✭ ᐅ ./func5
main: array_reference() 호출전 : str[hello][0x7fff674cba82]
array_reference: swap전 [hello][0x7fff674cba82]
array_reference: swap후 [world][0x7fff674cba82]
main: array_reference() 호출후 : str[world][0x7fff674cba82]
~/c-lecture (master ✘)✭ ᐅ
▶ 분석
- main()함수의 str='hello'를 array_reference()에서 'world'로 바꾸는 프로그램입니다.
- 결과를 보시면 main() 에서 호출전은 'hello', 호출후에는 'world'로 바뀌어 있는걸 확인 하실 수 있습니다.
물론 str의 주소와 array_reference()내에서의 주소도 동일합니다.
...
// call-by-reference 방식
array_reference(str);
- 이전 강의에서도 설명한대로 배열은 배열 이름 자체가 주소가 됩니다. 그래서 array_reference 호출시 배열변수명 str이 그대로 사용되었습니다.
...
// call-by-reference 방식
void array_reference(char *pStr) {
- 함수 파라메타에서도 포인터형으로 정의되어 있습니다.
- call-by-reference 방식은 c프로그램에서 상당히 많이 사용하는 방식입니다.
함수호출 방식과 호출된 함수의 파라메타 정의에 대해서 이해하시기 바랍니다.
반응형
'리눅스 C-언어 초급과정' 카테고리의 다른 글
16. 구조체(struct) (0) | 2022.11.21 |
---|---|
15. 문자열(배열) 다루기 (0) | 2022.11.17 |
14. 함수 (0) | 2022.11.16 |
13. 포인터 (0) | 2022.11.16 |
12. 문자열(string) (1) | 2022.11.16 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 리눅스
- array
- 파라메타
- #ifdef
- 재고
- 전처리기
- sharetravelplan
- String
- Call-by-value
- c프로그램
- 문자열
- memset
- Call-By-Reference
- #define
- Pointer
- struct
- 의유
- GCC
- Member
- memcpy
- IPC
- strcpy
- #include
- Linux
- 소켓
- While
- Clang
- 포인터
- C언어
- 배열
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
글 보관함