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 | //(1) #include <stdio.h> int Add(int a, int b) { return a+b; } void main() { int k = 2, m = 3; printf("sum = %d\n", Add(k,m)); } //(2) #include <stdio.h> int Add(int* pa, int* pb) { return *pa+ *pb; } void main() { int k = 2, m = 3; printf("sum = %d\n", Add(&k, &m)); } | cs |
(1) 와 (2)의 차이점을 아시겠습니까?
이전까지 계속 포인터를 봐왔으니 좀 감이 잡히시죠...
바로 그냥 값을 던져주느냐, 주소를 던져주느냐의 차이가 있었습니다.
값 복사 즉, Call By Value 같은 경우
값만 함수에 던져주다보니 접근을 할 수 없습니다.
이와 바대로 Call By Reference 같은 경우
주소를 던져주니 메모리에 접근이 가능합니다.
조금 더 자세하게 말씀드리자면,
(1) 과 같은 경우 말그대로 값만 던저주니 Add라는 함수에서 뭔 짓(?)을 하더라도
결국 Main 함수로 돌아온다면 아무런 변화가 없죠.
반면에, (2) 와 같은 경우 주소 자체를 던져주고
Add함수에서는 포인터 변수로 주소를 받았기 때문에,
접근자체가 가능하여 Add에서 처리된 값들이 실제로 main 함수의 변수에 적용이 됩니다.
Call By Value와 Call By Reference의 차이 아시겠습니까?
아무튼... 그런데 말입니다...
C/C++에서는 호출하는 코드보다 정의 하는 코드가 먼저 나와야되는 사실을 아시나요?
그러니까... 위에서 main보다 Add 함수가 더 위에 있잖아요?
이와 같이 main에서 호출했고 Add에서는 호출한 함수가 정의되어 있구...
이렇게 되어야 한다는 것입니다.
즉, 코드를 기계어로 바꾸는 컴파일러 친구에게
'얘가 함수야!' 라고 정보를 알려줘야한다는 것이죠.
그렇다면 main 함수를 계속 밑에 두고 함수들을 계속 선언해야할까요?
아닙니다. 함수를 위에 선언해두고 main 함수 밑에 해당 함수를 정의해도 된다는 이말입니다.
함수를 위에 선언할 때에는 함수의 정보를 선언해줘야합니다.
리턴값의 데이터형, 함수이름, 인자의 갯수, 각 인자의 데이터형과 순서 등등요...
이와 같이 함수의 원형에서 함수와 인자들의 이름을 제외한 나머지들을 시그니처라고 부르는데요,
시그니처를 기반으로 함수를 선언해주면 됩니다.
1 2 | #include <stdio.h> int Add(int* pa, int* pb); | cs |
이렇게요. 함수의 기본 정보들을 위에 선언해 두는 것이죠.
언제 다 함수를 main 위에 올려두겠어요...
이렇게 선언만 해두고 그때 그때 필요할 때마다 선언해두고 아래에 정의를 하면되죠.
물론, 규모가 커진다면 프로젝트를 새로 만들고 모듈화를 진행하겠지만요...
이건 저와 같이 초보자분들은 아직 모르셔도 될것 같습니다 ^^...
자 또 다른 이야기로 들어가봅시다...
함수에서 결과치를 받아오는 방법에는 두가지가 있습니다.
지난시간에 알아 봤던 반환값(return 값)을 사용하는 방법과
지금 알아볼 출력 매개 변수를 사용하는 방법이 있습니다.
매개변수에는
첫번째로, in parameter 즉, 입력 매개 변수
두번재로, out parameter 즉, 출력 매개 변수
이렇게 두가지가 있습니다.
입력 매개 변수는 고갱님에게 주는 값을 받기위한 목적을 가진 변수이고,
출력 매개 변수는 고갱님에게 값을 보내기 위한 목적을 가진 변수입니다.
또 추가적으로 말씀드리자면,
읽는 역활만 한다면 입력 매개 변수,
값을 변경시키는 것과 관련이 있다면 출력 매개 변수라고 설명드릴 수 있을 것 같습니다.
예시를 통해 함수에서 결과치를 받아오는 두번째 방법에 대해서 알아보도록 하겠습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #include <stdio.h> void Add(int a, int b, int* psum) { *psum = a+b; } void main() { int sum = 0; Add(2, 3, &sum); printf("%d\n", sum); } | cs |
Add 함수 선언에 보이는 int형 매개변수 a와 b는
Client가 주는 값을 받기 위한 목적으로 선언되어 있습니다. 즉, 입력 매개 변수라는 뜻이죠.
int* 형 psum이라는 포인터 변수와 같은 경우
Client에게 값을 내보내주기 위한 목적으로 선언되있음으로 바로 출력 매개변수입니다.
위의 예시 코드를 보자면,
2와 3을 보내고 sum이라는 int형 변수의 주소를 보냄으로
2와 3이라는 입력 매개 변수의 합을 출력 매개변수인 sum의 주소
즉, psum이라는 포인터 변수에 담는 것을 확인할 수 있습니다.
이는 자연스레 main 함수의 sum에 결과치를 가져오는 결과를 확인할 수 있습니다.
마지막으로 떠들어볼 내용은
바로 배열을 함수의 인수로 어떻게 전달할 수 있느냐 입니다.
C/C++ 에서는 배열을 함수의 인수로 전달할 때 통째로 전달 할 방법이 없습니다.
딱 한가지 방법이 있는데요, 여러분도 감 잡으셨을 만한
시작주소를 보내는 것입니다.
배열을 보내는 가장 확실한 방법입니다.
배열을 함수의 인수로 넘겨줄 때, 시작 주소와 원소의 갯수를 전달한다면
배열을 통째로 전달하는 방법과 같은 효과를 낼 수 있겠죠.
오늘은 여기까지 하도록 하겠습니다.
여러분 다음에 뵈요~!
'삽질의 현장 > - C' 카테고리의 다른 글
곱씹어보자 C!_#014_ 삽잡이의 두서없이 막하는 예제 코딩 (0) | 2015.06.26 |
---|---|
[삽잡이::C] 연산자 (0) | 2015.06.25 |
곱씹어보자 C!_#012_ 삽잡이의 두서없이 막말하는 함수(1) (0) | 2015.06.25 |
곱씹어보자 C!_#011_ 삽잡이의 두서없이 막말하는 문자열(2) (0) | 2015.06.24 |
곱씹어보자 C!_#010_ 삽잡이의 두서없이 막말하는 문자열(1) (0) | 2015.06.24 |