C언어 4일차

정혜창·2024년 12월 16일

독학

목록 보기
10/28
post-thumbnail

오늘은 내일배움캠프 Unreal이 시작한 첫 날이다. 하지만 그렇다고 이어온 공부를 놓을 순 없는 노릇이다. '오늘은 많이 바빴으니깐 개인공부를 안해도 되겠지' 라고 생각을 하게 되면 다음에는 다른 이유를 붙여서 안하게 되리라. 게으름을 버리자. 부지런해져라.


함수

  • 함수의 작성과 사용

함수란 기능을 수행하는 코드 단위를 말한다. 지금까지 사용해 왔던 main 함수가 대표적인 함수이다. 그리고 printf와 scanf도 함수이다. printf나 scanf 함수처럼 특정 기능을 미리 약속하고 프로그램에서 바로 사용할 수 있게 구현되어 있는 함수를 표준 라이브러리 함수 라고 한다. printf나 scanf 함수는 모든 예제에 있던 stdio.h 헤더 파일에 포함되어 있다. 혼자 공부하는 C언어 -서현우(개정판, 2023)- 208p 中'

C언어에서 표준으로 제공하는 함수 외에도 자주 사용하는 코드를 함수로 만들어 필요할 때 사용할 수도 있다. 함수를 만들려면 다음의 3가지가 중요하다.

  • 함수 정의 : 함수를 실제 코드로 만드는 것으로 함수의 기능을 구현한다.
  • 함수 호출 : 함수 호출을 해야지 함수를 사용할 수 있다.
  • 함수 선언 : 프로그램의 상단에서 어떤 함수를 사용할 것이라고 컴파일러에 정보를 주는 역할을 한다.

1. 함수 정의

여태까지 main 함수 하나로 프로그램을 만들었다. 이제부터는 main 함수와 또 다른 함수가 프로그램의 전체 기능을 나누어 수행하는 프로그램을 알아보자. 함수를 만들기 전에는 3가지를 먼저 생각해야 한다.

  1. 함수의 기능에 맞는 이름은 무엇인가?
  2. 함수가 기능을 수행할 때 필요한 데이터는 무엇인가?
  3. 함수가 수행된 후의 결과는 무엇인가?

간단하게 답한 이 질문이 바로 함수 원형(function prototype)을 이룬다. 이 내용을 코드 형식으로 쓰면 다음과 같다.

  • 함수 정의
반환형 함수명(매개변수1, 매개변수2) // <--- 함수 원형
{
	//함수가 수행하는 명령, 결과값을 돌려보냄
}

여기에 함수가 수행할 내용을 중괄호 안에 넣어 주면 함수가 완성된다. 이렇게 함수를 만드는 것을 함수 정의라고 한다.

  • 2개의 함수로 만든 프로그램(예제)
#include <stdio.h>

int sum(int x, int y);				  // sum 함수 선언

int main(void)						  // main 함수 시작
{
	int a = 10, b = 20;
    int result;						  // 두 정수를 더한 결과를
    								  // (result) 저장할 변수		
    result = sum(a, b);				  // sum 함수 호출
    printf("result : %d\n", result);
    
    return 0;
}							// main 함수 끝

int sum(int x, int y)		// sum 함수 정의 시작
{
	int temp;				// 두 정수의 합을 잠시 저장할 변수
    
    temp = x + y;			// x와 y의 합을 temp에 보관
    
    return temp;			// temp의 값을 반환
}							// sum 함수의 끝

함수를 다른 함수 안에서 정의할 수는 없다. 따라서 sum 함수는 main 함수와 별도의 구역에 만든다. 함수를 만들 때는 함수 원형을 가장 먼저 작성한다. 예제에서 함수 원형은 메인 함수가 끝나고 나온 int sum(int x, int y) 부분이다.여기서 반환형, 함수명, 매개변수를 표시한다.

반환형 : int
함수명 : sum
매개변수 : int x, int y

  1. 함수명은 함수의 기능을 충분이 예상할 수 있도록 적절한 단어로 식별자 사용 규칙에 따라 만든다.
  2. 매개변수는 함수가 처리할 데이터를 저장하는 변수로 함수명 옆의 괄호 안에 선언한다. 이때 매개변수의 자료형이 같아요 콤마로 구분해서 따로 선언한다.
  3. 반환형은 함수가 기능을 수행한 후 호출한 곳으로 돌려줄 값의 자료형을 적는다. 예제에서 sum 함수는 두 정수의 합을 반환해야 하므로 자료형으로 int를 사용하였다.

함수 원형이 완성되면 실제 함수의 내용을 중괄호 안에 작성한다.

int sum(int x, int y)
{
	int temp;
    
    temp = x + y;
    
    return temp;
}

함수 내에서 필요한 변수가 있다면 별도로 선언한다. 예제에서는 매개변수의 값을 더해 변수 temp에 잠시 저장했다가 return문에서 변수 temp에 저장해 두었던 값을, 함수를 호출한 곳으로 반환한다. 여기서 temp는 기능상 꼭 필요한 변수가 아니기 때문에 return (x + y); 처럼 두 수의 합을 바로 반환하는 것도 가능하다.

int sum(int x, int y)
{
	return(x + y);
}

2. 함수 호출과 반환

함수 호출

함수는 얼마든지 만들 수 있지만, 만든 함수가 모두 자동으로 실행되는 것은 아니다. 함수를 사용하려면 먼자 함수를 호출을 해야한다. 위의 2개의 함수로 만든 프로그램(예제)에서 main 함수 안에서 sum 함수를 호출하는 부분이다.

result = sum(a, b)

함수를 호출할 때는 이름을 사용하며 함수에 필요한 데이터를 괄호 안에 넣어 주는데, 이를 인수라 한다. sum 함수를 호출해서 a와 b를 더하려면 함수명과 함께 괄호 안에 a,b를 넣고 호출한다. 인수는 상수 or 변수를 쓸 수 있고 수식을 사용하면 수식의 결과값이 인수로 쓰인다.

sum(30, 40) 	// 상수 인수
sum(a*2, b/3) 	// 수식인수

함수를 호출할 때 입력된 인수 a, b의 값은 호출된 함수의 매개변수에 복사되어 사용된다. 예제의 코드를 보면 sum 함수가 호출되면 main 함수의 실행은 잠시 멈추고 비로소 sum 함수 정의 부분에 있는 코드가 실행된다. 이때 인수는(a, b) 함수의 매개변수(x, y)에 순서대로 복사되어 sum 함수 안에서 사용된다.

함수 반환

호출된 함수의 실행이 끝나고 값을 반환할 때 return문을 사용한다. 이때 temp의 값을 호출한 곳으로 반환한다. 이후 main 함수는 반환된 값을 대입 연산으로 result에 저장하고 잠시 중단했던 함수의 나머지 부분을 실행한다.

컴파일러는 함수를 호출할 때 반환값을 저장할 공간을 미리 준비해 둔다. 이 공간은 컴파일러가 별도로 확보하는 공간이며 식별할 수 있는 이름이 없으므로 계속 사용할 수 없다. 대신 저장된 반환값을 대입 연산으로 다른 변수에 복사하거나 수식에 바로 사용하는 것은 가능하다.


3. 함수 선언

함수 선언은 컴파일러가 새로 만든 함수를 인식할 수 있도록 알리는 역할을 한다. 앞의 위의 2개의 함수로 만든 프로그램(예제)에서 3행이 sum 함수를 선언하는 문장이다.

int sum(int x, int y);

선언방법은 그저 함수 원형에 세미콜론을 붙이면 된다. 함수 선언은 main 함수 앞에 하며 매개변수 이름은 생략할 수 있다.

int sum(int, int);

그러나 함수 정의가 있는데 왜 함수 선언이 필요할까?

  • 이유_1 : 함수 선언에서 반환값의 형태를 확인한다.
    앞서 말했듯이 컴파일러는 컴파일할 때 함수를 호출한 자리에 반환값과 같은 형태의 저장 공간을 준비한다. 따라서 함수를 호출하기 전에 선언을 통해 반환형을 미리 컴파일러에 알릴 필요가 있다. 그러나 함수 정의에서도 반환형을 확인할 수 있으므로 함수 호출 이전에 함수를 정의하는 방법도 있다. 즉, 함수 선언이 없으면 함수 정의는 항상 함수 호출 이전에 있어야 한다.

  • 이유_2 : 함수의 호출 형식에 문제가 없는지 검사한다.
    함수 선언문에는 매개변수의 개수와 형태에 대한 정보가 있으므로 호출할 때 정확한 값을 주는지 검사할 수 있다.


4. 확인 문제

187cm를 미터 단위로 환산해 출력하는 프로그램이 완성되도록 하시오. 단 cm를 m로 환산해 반환하는 함수를 만들고 함수 호출을 통해 구현하시오.

#include <stdio.h>

double transform(double x);

int main(void)
{
	double res;
    
    res = transform(187);
    printf("%.2f\n", res);
    
    return 0;
}

double transform(double x)
{
	double temp;
    temp = x / 100.0;				// result (x / 100);
    return temp;
}

회고

처음 함수를 만들다보니 이런 간단한 문제를 푸는데도 많이 서툴렀다. 우선 습관적으로 int를 쓰는 버릇을 버려야겠다는 생각을 했다 결과를 실수로 받아야 하는데 int transform으로 선언하질 않나 변수를 int temp로 설정하기도 하고.. 왜 계속 결과가 안나오지 하면서 해매게 되었던 것 같다. 진짜 나는 머리가 돌대가리 일수도.. 왜 나는 프로그래밍에 재능이 없는걸까 하... 이번 문제는 예제처럼 풀긴했는데 사실 작성을 해보면서 느끼지만 함수 정의는 main 함수 앞에 쓰는게 main에서 변수를 설정하는데에도 좀더 편할 것 같긴하다. 하지만 코드가 지저분해지진 않을까 생각도 든다.

따라서 이번에는 앞에 함수 선언을 하지않고 main함수 앞에 함수 정의를 넣어 187로 고정된 상수가 아닌 입력한 값을 m로 변환해주는 코드를 한번 만들어 보았다.

#include <stdio.h>

double transform(int x)
{
	double temp;
    temp = x / 100.0;
    return (temp);
}

int main(void)
{
	int i;   		// 입력을 받을 변수
    double res;		// 함수의 반환 값을 저장할 변수
    
    printf("키를 입력하세요 : ");
    scanf_s("%d", &i);
    
    res = transform(i);
    printf("당신의 키는 : %.2lfm 입니다.\n", res);
    
    return 0;
}

굳굳 매우 잘 돌아간다. 하지만 이번에 작성하면서 앞에 배웠던 '자동 형 변환'이 살짝 애매 했던것 같다. i 변수를 double로 할까 수십번을 고민했는데 int로 설정해도 (temp = x / 100.0)에서 다시 double형으로 바뀌는게 맞는 것 같아 그냥 작성했다. 다행히도 문제없이 컴파일되었다.

profile
Unreal 1기

0개의 댓글