자료실/C언어

C언어 - 함수(function)

자료수집중 2020. 6. 18.
반응형

 

함수는 프로그램의 기본 구성 요소입니다. 

printf(), scanf()등도 표준 라이브러리 함수입니다.

 

함수의 형태에대해 알아보겠습니다.

반환형 함수명(매개 변수, 매개 변수 ......)
{
    코드
}

반환형은 함수가 실행을 종료한 후 호출된 곳으로 반환하는 값으로 int, float, char등 자료형이 들어갑니다.

아무값도 반환하지 않으려면 void를 사용하면 됩니다.

반환형을 아무것도 사용하지 않으면 int형으로 반환되나 int형으로 반환을 해도 꼭 명시해주는게 좋습니다.

 

함수명은 함수를 호출할때 사용할 이름으로 첫글자에 숫자가 들어갈 수 없고 중복된 이름이 사용 불가능 합니다. 특수문자는 _ 만 사용 가능합니다.

 

매개 변수파라미터(Parameter)라고도 합니다. 자료형과 변수명으로 구성되며 함수의 외부에서 들어오는 데이터입니다.

매개 변수는 여러개를 선언 할 수 있고 없을 경우에는 비워두거나 void를 입력하면 됩니다.

 

 

예제를 통해 더 알아보겠습니다.

보통 함수를 사용할때는 main()앞에 함수를 정의 하거나 함수원형을 선언해야합니다.

void world()   //함수 정의
{ 
    printf("Hello World \n");
}
int main(void)
{
    world();

    return 0;
}
void world(); //함수원형 선언

int main(void)
{
	world();

	return 0;
}
void world()
{
	printf("Hello World \n");
}

만약 main앞에 함수 정의나 함수원형을 선언하지 않은 예를 보면

int main(void)
{
	world();

	return 0;
}
void world()
{
	printf("Hello World \n");
}

에러가 발생합니다.

이유는 c언어는 절차 지향입니다. 위에서부터 아래로 실행을합니다.

그래서 함수를 정의하여 아래에 main이 사용하게 하거나 함수원형을 선언해서 해당 함수의 존재를 미리 알려야 합니다.

 

다른 예로 보겠습니다.

int sum_1(int num1, int num2, int num3);

int main(void)
{
	int a, b, c;
	printf("숫자 3개를 입력해주세요 ");
	scanf("%d %d %d", &a, &b, &c);
	printf("입력된 3개의 숫자의 합은 : %d 입니다.", sum_1(a, b, c));

	return 0;
}
int sum_1(int num1, int num2, int num3) {
	return num1 + num2 + num3;
}

sum_1를 자세히 살펴보면 변환형으로 int가 선언됐고 매개변수는 int형 3개를 선언했습니다.

return으로 3개의 매개변수 합을 반환했습니다.

return이 반환하는 값은

return 5;
return num;
return num1+num2;
return ; //아무값도 반환하지 않을때

다양한 방법할 수 있습니다.

void경우는 return은 하지 않아도됩니다.

다른 자료형의 경우는 return을 사용하지 않아도 실행은 되지만 엉뚱한 값이 반환됩니다.

함수 원형에서 3개의 매개변수를 선언했다면 함수의 정의에도 꼭! 3개의 매개변수를 넣어야 합니다.

그리고 해당 함수를 사용할때 같은 자료형으로 매개변수의 수와 같은 인자를 전달해야 합니다.

여기서 인자,인수(Argument)는 함수를 사용할때 전달되는 값을 말합니다.

printf("입력된 3개의 숫자의 합은 : %d 입니다.", sum_1(a, b, c)); //a, b, c가 인자

다른 자료형의 값의 인자를 전달하면 반환값이 엉뚱하게 나오거나 에러가 발생합니다.

 

 

매개변수에 대해서 조금 더 가보면

매개변수는 포인터도 가능합니다.

매개변수의 일반적인 변수를 사용할때와 포인터를 사용할때의 다른점을 보겠습니다.

먼저 일반적인 변수를 사용하면

void point_1(int num1, int num2, int num3);
int main(void)
{
	int a = 10, b = 11, c = 12;
	point_1(a, b, c);
	printf("%d %d %d \n", a,b,c);

	return 0;
}
void point_1(int num1, int num2, int num3) {
	num1 = 100;
	num2 = 200;
	num3 = 300;
}

main에서 선언한 변수를 전달받아 함수에서 매개변수에 새로운 값을 대입해도 main에서 대입한 값은 변하지 않습니다. 즉 매개변수는 단순하게 값만 전달할 뿐 함수 외부에는 영향을 줄 수 없습니다.

하지만

매개변수에 자료형 뒤에 *(Asterisk)를 붙여서 포인터 형태로 변경하면

void point_1(int *num1, int *num2, int *num3);
int main(void)
{
	int a = 10, b = 11, c = 12;
	
	point_1(&a, &b, &c);
	printf("%d %d %d \n", a,b,c);

	return 0;
}
void point_1(int* num1, int* num2, int* num3) {
	*num1 = 100;
	*num2 = 200;
	*num3 = 300;
}

함수에서 대입한 값으로 변하는 모습을 볼 수 있습니다.

전달인자도 &를 사용해서 메모리 주소를 보내줍니다.

즉 포인터 선언된 매개변수는 인자의 메모리 주소를 가져와 직접적으로 접근해서 사용할 수 있습니다.

 

다음으로 재귀함수에 대해 알아보겠습니다.

재귀함수는 함수에 자기 자신을 다시 호출하는것입니다.

void world(); 

int main(void)
{
	world();

	return 0;
}
void world()
{
	printf("Hello World \n");
	world();
}

world()함수에 world()를 다시 호출하면서 무한하게 반복하여 호출합니다.

그래서 보통 재귀함수를 사용할때 특정 조건을 걸고 사용합니다.

 

재귀함수를 이용해서 만들 팩토리얼(factorial)을 통해 보면

int factorial(int num) {
    if (num == 1)
        return  1;

    return num * factorial(num - 1);
}
int main(void)
{
    printf("%d \n", factorial(5));

    return 0;
}

factorial(5)이 호출되고 다음에

factorial(4) 다음으로 factorial(3), factorial(2), factorial(1)까지 호출이 됩니다.

다시 factorial(1)부터 return이 되면서 factorial(5)이 마지막으로 120을 반환합니다.

 

 

 

 

댓글