리메이크 중/C,C++ 이론 중심

C(&C++) 이론 15. 함수

라이피 (Lypi) 2023. 1. 4. 18:09
반응형


내용 참고

YES C (정보공학연구소/생능출판사)

혼자 연구하는 C/C++ (Soen.kr/와우북스)

Microsoft Docs (구 MSDN)


 함수

Ⅰ. 프로그래밍에서의 함수

ⅰ. 절차지향 프로그램에서 함수의 의의

함수란 C로 만들어진 프로그램에서 프로그램을 구성하는 단위이다.

■ 이는 C언어가 기본적으로 절차지향 프로그래밍 방법론에 따라 설계되었기 때문이다.

◆ 절차지향 프로그래밍 (Procedual Oriented Programming)

■ 절차치향 프로그래밍에서는 분할정복전략으로 문제를 해결한다.

◆ 분할 정복 전략 (Divide and Conquer)

■ 분할정복전략이란 큰 문제를 여러개의 작은 문제로 나눠서 해결하는 문제 해결 전략이다.

■ C 프로그램은 주로 함수라는 기능별 문제 해결 단위를 모아서 큰 문제를 해결한다.

▶ 객체 지향 프로그램에서는 함수 대신에 객체가 프로그램의 단위를 이룬다.

▶ 함수형 프로그래밍에서의 함수는 '순수 함수'를 의미하며 절차지향 프로그래밍에서 말하는 함수와는 개념이 좀 다르다.

 

★  클래스 안에 있는 함수는 메소드라고 한다. 추후에 클래스를 공부할 때 참고하자.

 

ⅱ. 함수의 장점

■ 프로그램내에서 반복되는 부분을 함수로 처리함으로 불필요한 반복을 줄이고 메모리를 절약할 수 있다.

■ 프로그램의 기능에 따라 함수로 만드는 것으로 프로그램이 모듈화되어 프로그램의 가독성을 높일 수 있다.

■ 기능 단위로 제작된 함수는 다음 프로그램을 제작할 때 재사용이 가능하다.

■ 함수의 내부 구조를 몰라도 매개변수와 반환값만 맞으면 타인이 만든 함수를 사용할 수 있다.

 

Ⅱ. C/C++의 함수의 종류

ⅰ. main 함수

■ C/C++ 프로그램이 실행되면 운영체제는 main함수를 실행하며 main함수가 끝나면 프로그램도 종료한다.

■ 즉, main함수는 C/C++ 프로그램의 시작과 끝의 역할을 수행한다.

■ 그러므로 main함수는 프로그램내에 단 하나만 존재해야한다.

■ main 함수는 기본적으로 int값을 반환하지만 반환값이 없을 수도 있다.

▶ main함수에 대해서는 추후에 공부해야 하는 쉽지 않은 내용이 많다.

ⅱ. 표준 함수

printf나 scanf와 같이 언어 자체에서 제공되는 함수를 의미한다.

■ 하지만 C/C++ 같은 경우에는 언어 자체에서 라이브러리를 제공하는 것일 뿐 함수가 언어에 내장되어 있지는 않다.

■ 그러므로 표준 함수를 사용하려면 그에 맞는 라이브러리 파일을 include 명령어로 링킹해줄 필요가 있다.

ⅲ. 사용자 정의 함수

프로그래머가 필요에 따라 직접 정의하는 함수를 의미한다.

ⅳ. 매크로 함수 (or 인라인 함수)

실제 함수 정의는 아니지만 #define 선언문을 이용해서 함수처럼 사용할 수 있는 수식을 만든 것을 의미한다.

■ 매크로 함수는 컴파일 과정에서 코드의 문자열을 수식으로 치환하기에 '인라인 함수'라고도 부른다.

■ 매크로 함수는 속도면에서는 유리하지만 파일의 크기가 커진다는 단점이 있다.

■ 무엇보다도 단순 치환이기 때문에 의도와 다르게 작동할 수도 있으므로 사용시 세심한 주의가 필요하다.

 

#include <iostream>
using namespace std;

#define ab(a) ( (a)>0?(a):-(a) )

int main()
{
	cout << ab(-123);

	return 0;
}

■ 단순 치환이라는 부분 때문에 매크로 함수를 만들 때는 주의할 점이 많은데 이는 추후에 자세히 다룰 예정이다.

 

반응형

 

Ⅲ. 함수 정의하기

ⅰ. 함수의 정의

■ 함수의 기본 구조는 아래와 같다.

반환데이터타입 : 함수가 최종적으로 반환하는 값의 데이터 타입. 없으면 void라고 명시해야한다.

함수명: 함수의 이름, 식별자로 구분되므로 C언어의 이름짓기 규칙을 지켜야 한다.

인수목록 : 함수 내부로 전달되는 값. 없으면 비워놓는다. 

■ 본체 : 함수가 호출되면 실행할 명령 목록.

■ 우측의 함수는 정수 하나를 입력받고 정수 하나를 반환하는 함수로 입력된 값의 절대값을 반환한다.

 

ⅱ. 함수 본문 작성하기

■  함수의 기본구조에 맞게 함수의 틀을 마련했다면 함수의 본문을 작성해야 한다.

■  인수는 함수를 호출한 호출원에서 함수에게 넘겨주는 값이다.

■  두 함수 사이의 정보 교환에 사용된다는 의미에서 매개변수라고도 한다.

■  인수가 필요하지 않다면 인수 목록을 비워놓거나, 인수 목록에 void라고 쓰면 된다. 

■  물론 인수 목록에 굳이 void를 쓰는 경우는 아직 본 적이 없다.

■  함수 정의의 인수는 영어로 parameter, 함수 호출시에 전달하는 인수의 값은 argument라고 한다.

■  함수 본문에서 parameter를 사용할 땐 parameter에 쓴 변수명을 그대로 쓰면 된다.

■  함수 안에서 새로운 변수를 정의하는 것도 가능하다.

■  다만 이렇게 정의한 변수는 스코프 규칙에 의해서 정의한 함수 안에서만 사용할 수 있다.

■  이를 이용하여 원하는 작업을 수행하고 나서 return문을 이용하여 값을 반환해주면 된다.

■  반환값이 없는 함수를 만들었어도 return문을 쓰면 함수가 종료된다.

■  즉, return문을 사용하면 분기에 따라 중간에 함수를 끝내고 값을 반환시킬 수도 있다.

■  반환값이 void인 경우 return문을 생략할 수도 있지만 이는 컴파일러가 return문을 추가하는 것으로 추천하지 않는다.

■  대신 반환값은 없으므로 return; 만 쓰면 된다.

■  반환값이 지정된 타입이 아닐 경우 컴파일러는 암시적 형변환을 시도하고 실패하면 에러를 표시한다.

■  main 함수도 함수이기 때문에 return 0;를 만나면 종료된다.

 

ⅱ. 만든 함수 사용하기

■  표준 함수를 사용했던 것 처럼 사용하면 된다.

■  반환 타입이 들어가는 자리에는 같은 반환 값을 가진 함수를 항상 쓸 수 있다.

■  예를 들어 정수를 인수로 받는 함수의 인자로 정수를 리턴하는 함수를 쓸 수도 있다.

■  선언과 정의를 분리했다면 선언만 있어도 사용할 수 있다. 

■  선언하고 사용했는데 정의가 없다면 링크 과정에서 에러가 나니 주의해야한다.

Ⅳ. 선언과 정의 분리하기

ⅰ. 라이브러리 링킹과 함수 선언

■ 프로그램의 시작은 main함수이므로 정의한 함수는 기본적으로 main함수에서 사용된다.

■ 그런데 C/C++ 컴파일러는 소스 코드를 위에서 아래로 해석한다.

■ 그러므로 함수 정의나 라이브러리는 기본적으로 main함수 위에 위치해야한다.

■ 이 때 main 함수 위에는 함수의 원형만 선언하고 실제 정의는 main 함수 아래에서 할 수도 있다.

 

#include <iostream>
using namespace std;

int main()
{
	cout << a(-19);     // 오류C3861 : 식별자 a를 찾을 수 없습니다.
	cout << abs(-123);

	return 0;
}

int a(int a) {
	return a;
}

int abs(int a) {
	return a > 0 ? a : -a;
}

■ 위의 코드는 main함수에서 함수 a를 호출하는 시점에서 오류가 발생한다.

◆ 참고로 함수 abs는 오류가 나지 않는데, 아마 abs라는 함수가 헤더파일에 이미 정의되어 있기 때문이다.

◆ 이런 경우 추후에 에러를 유발할 가능성이 높으므로 주의하는 것이 좋다.

 

#include <iostream>
using namespace std;

int a(int a); // 함수 a에 대한 원형만 미리 선언

int main()
{
	cout << a(-19);
    
	return 0;
}

//함수 a에 대한 실제 정의
int a(int a) {
	return a;
}

■  위와 같이 main 함수 위에 함수 a에 대한 원형을 선언해주면 해결된다.

■  이런식으로 함수의 선언과 정의를 분리하는 것은 함수의 정의가 길 경우 큰 도움이 된다.

■  추후에는 함수를 헤더파일에 정의 및 선언하고 헤더를 가져다 쓰는 경우가 많다.

■  헤더파일에는 이 외에도 매크로 상수나 열거형 타입, 매크로 함수, 사용자 정의 자료형 등이 선언 및 정의되어 있다.

 

ⅱ. 함수 원형

■  함수의 원형이란 함수의 본체를 정의하기 전에 함수의 형태를 컴파일러에게 먼저 알려주기 위해서 사용하는 함수 선언문이다.

■  함수 원형은 변수데이터타입 함수명(인수목록); 의 형태로 작성하면 된다. (세미콜론 필수!)

■  함수의 원형 선언에는 인수의 타입만 적고 인수의 이름은 생략할 수도 있지만 사용시 의미를 명확히 하기위해서 권장하지는 않는다.

■  함수 원형을 사용하지 않을 경우에는 아래와 같이 함수의 정의가 main함수 위에 와야한다.

■  이는 사용자 정의 함수가 여럿이거나 함수간의 상호 참조등이 이루어질 경우 매우 불편하며 문제를 일으킬 수도 있다. 

■  아래 예제의 경우 max2의 함수 정의와 max1의 함수 정의의 순서가 바뀌면 에러가 일어난다.

   


   ⑤ 하지만 원형을 사용하면 원형이든 정의든 순서가 상관없어진다. 

 

 

반응형