레이블이 인자인 게시물을 표시합니다. 모든 게시물 표시
레이블이 인자인 게시물을 표시합니다. 모든 게시물 표시

2015년 5월 9일 토요일

C++에서 함수의 기본값 인자 (default parameter)

 C++에서 (C언어에서는 지원되지 않음) 함수가 호출될 때 입력 인자에 값이 넘어오지 않는다면 미리 정해진 값을 함수 내부에서 가지도록 할 수 있다. 이렇게 기본값을 가지는 함수의 인자를 기본값 인자(default parameter)라고 하며 함수의 선언부에서 예를 들면 다음과 같이 명시해 주어야 한다.

void func(int ia=0); // 함수의 선언에 ia의 기본값을 10으로 지정
….
int func(int ia) { //함수 정의. ia는 기본값 10을 가진다.
   return ia+10;
}

변수 ia는 호출될 때 값이 넘어오지 않으면 자동으로 0값을 가지도록 선언되었다. 즉, 이 함수를 호출할 때 입력인수를 주어도 되고 안 해도 된다.
func(); // 변수 ia는 0값을 자동으로 갖는다.
func(10); // 변수 ia에 10값을 넘겨준다.
 만약 디폴트 입력 인수기능이 없이 함수 중복으로만 이를 구현한다면 다음 그림의 좌측과 같이 두 개의 함수를 별도로 작성해야 할 것이다.

void func() {
   int ia = 0;
   // 함수 본체
   ....
}
void func(int ia) {
   // 함수 본체
   ....
}
void func(int ia = 0);
함수 중복으로 구현한 경우
디폴트 입력 인수 함수로 간략화

이것을 살펴보면 기본 인자 기능이 프로그램을 상당히 간결히 해주는 유용한 기능임을 알 수 있다.

#include "stdio.h"

void print(char *name = "John");// 기본값을 지정

int main(void)
{
print();
print("Jang-Hyun Park");
}

void print(char *name)
{
printf("Hi. My name is %s\n", name);
}

Hi. My name is John
Hi. My name is Jang-Hyun Park
 다른 예를 들어보면 다음과 같다.
void send(int ia, string str=“Hello”);
이 함수는 다음과 같이 두 가지로 호출이 가능하다.

send(10);
send(10, “Hi”);
 
기본값 인자가 설정된 변수만 생략 가능하다는 점에 유의해야 한다. 따라서 다음과 같은 호출은 오류를 발생시킬 것이다.
send(); //오류 발생
send(“Hi”); //오류 발생
 만약 다음과 같이 디폴트 입력 인수를 두 개 가진 함수라면
void sum(double da, double db=10.0, double dc=20,0);
다음과 같이 세 가지 방법으로 호출할 수 있다.
sum(1.0); // da는 1.0, db는 10.0, dc는 20.0 값을 갖는다.
sum(1.0, 2.0); // da는 1.0, db는 2.0, dc는 20.0 값을 갖는다.
sum(1.0, 2.0, 3.0); // da는 1.0, db는 2.0, dc는 3.0 값을 갖는다.
 디폴트 입력 인수를 가진 함수를 선언할 때 주의할 점은 이것들이 모두 끝 쪽에 몰려있어야 하며 디폴트 입력 인수를 가지는 변수 다음에 일반 변수는 못 온다는 것이다. 다음 예는 모두 잘못된 것이다.
 void sum(int ia, int ib=5, int ic, int id=10);// 에러 발생
 void sum(int ia=10, int ib, int ic);// 에러 발생
그리고 다음과 같은 함수 중복도 오류를 발생한다.

void print(string stra);
void print(string stra = “Hello”); // 허용되지 않는 함수 중복
 
그 이유는 두 함수가 입력 인수의 개수와 형이 같기 때문이다. 그리고 다음과 같은 함수 중복도 오류를 발생한다.
void func(int ia, string strA=“Hi”);
void func(int ia); // 허용되지 않는 함수 중복
두 함수는 분명히 입력 인수의 개수가 다르지만 만약 func(10) 이라고 호출했을 때 두 개 중 어느 것을 호출해도 문제가 없기 때문에 컴파일러는 오류를 발생시킨다.

2015년 5월 6일 수요일

C/C++에서 배열을 함수의 인자로 넘기는 방법

 함수의 인자로 배열을 넘겨줄 때 어떻게 사용해야 되는지 살펴보도록 하겠다. 함수의 선언에서 배열이 인수인 경우 다음과 같이 사용한다.
데이터형 함수명(데이터형 배열명[])
이렇게 배열 크기를 알 수 없는 형태로 선언하는 이유는 C언어가 내부적으로 배열을 넘기는 것이 아니라 배열의 시작 주소를 넘기기 때문이다. 배열명은 함수 선언에서는 생략 가능하다. 내부적인 처리에 대한 자세한 내용은 포인터에서 더 자세히 설명하도록 하겠다.


배열을 넘겨받는 함수의 선언 예를 들어 보면 다음과 같다.
int func(int ia[]); //❶
int func(int []); //❷
위 두 가지는 컴파일러 입장에서는 동일하다. 왜냐면 배열명이 함수의 선언에서는 의미가 없기 때문이다. 따라서 함수의 인수가 int형 배열이라고 선언하는 것은 ❷번으로 충분하다.


 이렇게 선언된 함수를 호출할 때는 배열명을 이용해서 다음과 같이 한다.


func(arr)
예를 들어서


int arr[] = {1, 2, 3};
func(arr);
이렇게 하면 arr라는 int형 배열을 함수 func()로 넘겨주게 된다. 배열을 함수로 넘겨줄 때는 배열명만을 써준다는 것에 다시 한 번 주의하자.
 다음 예제는 함수에 배열이 인수로 넘어오는 것이다.
#include <stdio.h>
void showArray(int []);
int main(void) {
   int ia[] = {10,20,30,40,50};
   showArray(ia);
}
void showArray(int ia[]) {
   for (int k=0; k<5; k++)
       printf("ia[%d] = %d\n", k, ia[k]);
}


실행 결과 :
ia[0] = 10
ia[1] = 20
ia[2] = 30
ia[3] = 40
ia[4] = 50
Press any key to continue...
이 예제의 경우 showArr()함수로 넘어오는 배열은 크기가 5로 고정되어 있다고 가정하고 작성한 것이다.
 그런데 사실 함수는 인수로 넘어온 배열의 크기를 알 수 있는 방법이 없다. 따라서 다음 예제와 같이 함수에 배열을 넘길 때 배열의 크기를 추가로 넘겨주는 방법도 자주 쓰인다.


#include <stdio.h>
void showArray(int [], int);
int main(void) {
  int iaA[] = {10,20,30,40,50};
  int iaB[] = {-1, 0, 1};
  showArray(iaA, 5);
  showArray(iaB, 3);
}
void showArray(int ia[], int iLength) {
   for (int k=0; k<iLength; k++)
       printf("ia[%d] = %d\n", k, ia[k]);
}


실행 결과 :
ia[0] = 10
ia[1] = 20
ia[2] = 30
ia[3] = 40
ia[4] = 50
ia[0] = -1
ia[1] = 0
ia[2] = 1
Press any key to continue...
이 예제의 함수 선언부를 따로 보면 아래와 같다.


void showArray(int [], int);


조금 이상하게 보일지 몰라도 함수의 선언부에서는 변수명을 생략할 수 있다고 전에 설명한 적이 있다. 위의 경우는 첫 번째 배열명과 두 번째 변수명을 모두 생략한 경우이다. 즉, 이 함수의 첫 번째 인수는 int형 배열이고 두 번째 인수는 int형 변수라고 선언하는 것이다.



2015년 5월 1일 금요일

C++ 의 함수의 인자 전달


C++에서 함수의 인자 전달
C언어,C++,함수,인자,function,argument,전달



 함수는 인자(argument)를 통해서 기능 수행에 필요한 값들을 전달 받는다. 또한 함수는 결과값을 반환하는 경우도 있고 반환 값이 없는 함수도 있다. 이렇게 함수와 호출자 사이의 정보 교환은 인자반환값이라는 매개체를 통해서 이루어진다.

  • 인자(argument) : 함수가 값을 받는 매개 변수
  • 반환값(return value) : 함수가 되돌려 주어야 할 수행 결과값

C++ 언어에서 함수 인자 전달 매커니즘을 한 번 살펴보도록 하자.

//호출부
int main() {
   int is = add(ix, 20); //① ix, 20은 실인자
}

//피호출부
int add(int ia, int ib) { //② ia, ib 값은 가인자
   int isum = ia + ib;
   return isum;
}

호출하는 함수의 인자를 실제 값이라는 의미로 실인자라고 하고 호출되는 함수에서는 가인자라고 한다. 실인자와 가인자 사이에 데이터를 넘겨주는 방식은 값에 의한 호출(call-by-value) 방식으로서 실인자의 값이 복사되어 넘겨진다.

 호출되는 함수의 return 명령은 이 함수가 내부적으로 연산을 수행한 후 반환값이 있다면 그 뒤에 반환값을 두게 된다. 반환값이 없다면 return문만 단독으로 사용한다. 입력 인자는 없을 수 도 있고 여러 개일 수 있지만 반환값은 없거나 한 개뿐이다.

 위의 예제에서처럼 호출하는 함수는 반드시 main()함수이어야 되는 것은 아니다. 어떤 함수에서든지 다른 함수를 자유롭게 호출할 수 있다. 심지어 어떤 함수 내부에서 그 함수 자체를 호출할 수도 있으며 이를 재귀 호출(recursive call)이라 한다.

사용자 함수를 작성하여 사용하려면 다음과 같은 단계를 따른다.

  1. 함수의 기능 및 인자, 반환값을 설계한다.
  2. 정해진 형식에 따라 함수를 선언한다.
  3. 함수의 본체 부분을 작성한 후 (정의) 호출하여 사용한다.
  4. 호출하는 쪽의 인자의 개수와 형식 그리고 반환값의 형식이 모두 정의된 대로여야 한다.

 앞에서도 언급했지만 C/C++ 언어의 값에 의한 호출 방식은 호출부와 피호출부의 인자들 사이의 관계에서 값만을 전달하는 방식으로 데이터값을 복사하여 전달한다. 이는 문서를 복사했을 때 복사본을 아무리 수정해도 원본이 변하지 않는 것과 같은 원리이다.

 다음 예를 보자.

//호출부:
int main() {
   int ia = ib = 10, ic;
   ....
   ic = sub(ia, ib); //❶
   ....
}

//피호출부:
int sub(int ia, int ib) { //❷
   ia -= ib;
   return ia;
}

호출부 ❶에서의 변수 ia, ib와 피호출부 ❷에서의 변수 ia, ib는 변수명은 같으나 저장 공간이 다른 완전히 다른 변수라는 점을 유의해야 한다. sub()함수 내부에서 ia값은 바뀌지만 그렇다고 main()함수 안의 변수 ia가 바뀌는 것은 아니다. 서로 다른 변수이기 때문이다.

호출부에서 반환값을 받을 때도 피호출된 함수에서 반환값이 복사되어 새로운 변수를 통해 전달된다. 즉, return ia; 실행문에 의해서 ia변수의 '값'이 복사되어 호출부의 변수 ic에 전달되는 것이다. 이것이 값에 의한 호출 방식의 동작 원리이다.