Priv's Blog

C++의 함수 프로토타입 본문

Dev. Study Note/C++

C++의 함수 프로토타입

Priv 2024. 6. 26. 20:59


 

 

1. 함수

C++에도 코드 재활용 수준과 가독성을 높여주는 함수가 존재합니다.

함수는 데이터를 입력받으면 이를 활용해 특정한 기능을 수행한 뒤, 적절하게 가공된 출력을 하는 역할을 수행합니다.

여기서 데이터의 입력은 '매개변수', 데이터의 출력은 '반환 값'이라는 용어로 칭합니다.

매개변수와 반환 값은 존재하지 않을 수도 있으며, 그 종류와 개수도 무궁무진합니다.

반복적으로 사용되는 코드의 일부분을 함수로 처리하면 동일한 기능을 수행해야 할 때 그 함수를 '호출'하면 되므로, 코드의 가독성과 재활용성을 높여줄 수 있습니다.

함수의 이름이 곧 함수이 기능을 의미합니다.

이 때문에 함수를 호출하는 것만으로도 그 함수의 실제 내용물을 모르더라도 어떠한 기능이 수행될 것인지를 쉽게 파악할 수 있습니다.

이러한 점 덕분에 OOP(객체 지향 프로그래밍) 개념에서 주로 언급되는 '캡슐화'를 달성하는데 큰 역할을 하기도 합니다.

 


 

2. C++ 함수의 특징

C++에서 함수를 선언할 때는 함수의 '프로토타입'을 선언해야 한다는 특징이 있습니다.

즉, C++에서의 함수 사용은 '함수 정의', '함수 프로토타입 선언', '함수 호출'까지 총 3단계로 이루어집니다.

#include <iostream>
using namespace std;

void simple();    // Function Prototype


void simple() {    // Function Definition
    cout << "simple()" << endl;
}

int main() {
    cout << "call the simple()" << endl;
    
    simple();    // Function Call
    
    return 0;
}

 


 

3. 프로토타입 (Prototype)

C++의 함수에는 프로토타입이라는 개념이 있다고 언급했습니다.

그렇다면 왜 프로토타입이라는 개념이 필요한 걸까요?

먼저 함수를 선언할 때, 우리가 알아야 하는 중요한 정보들에 대해 알아봅시다.

함수를 선언할 때는 아래와 같이 작성해야 하며, 이는 다른 언어에서도 거의 동일합니다.

void FunctionVoidNotReturn() {
}

int FunctionIntReturn() {
    return 0;
}

float FunctionfloatReturnWithInt(int i) {
     cout << i << endl;
     
     return 3.14;
}

위 코드의 3가지 함수는 서로 다른 형태이지만, 문법은 같습니다.

반환 타입, 함수 이름, 매개변수를 담는 괄호, 함수의 시작과 끝을 나타내는 중괄호, 함수의 내용을 결정하는 코드와 반환 값으로 이루어져 있습니다.

이는 함수가 어떠한 구성으로 이루어져 있는지를 결정합니다.

즉, 이 함수가 어떤 값을 반환할 것인지, 어떤 매개변수를 받을 것인지 등을 알 수 있다는 것입니다.

이러한 정보는 컴파일러에게도 중요한 정보가 됩니다.

어떤 동작을 수행하는 함수이든지 간에, 일단 이러한 형태의 함수가 사용될 것이라는 걸 컴파일러에게 알려주는 작업은 필요합니다.

이는 컴파일러가 오류를 잡아낼 때도 큰 도움이 됩니다.

매개변수로 int 타입의 값을 받는 함수인데, float 타입의 값을 제공했다면 컴파일러가 이를 인지하고 오류를 잡아낼 수 있겠죠.

또한 함수가 동작을 마치고 나면 계산이 끝난 어떠한 값을 어느 공간에 필히 저장해야 할 것입니다. CPU가 사용하는 레지스터일 수도 있고, 아니면 메인 메모리가 될 수도 있겠죠.

만약 함수의 프로토타입이 double 타입으로 선언되었다면, 컴파일러는 double 타입을 다루는 방법을 알고 있기에, 함수의 동작이 끝나고 값이 저장된 위치를 어떻게 찾아서 어떻게 값을 가져와야 하는지를 알고 있습니다.

즉, 얼마나 많은 바이트를 탐색해야 하는지를 알고 있는 것입니다.

이러한 정보가 없다면, 컴파일러는 그저 어떤 함수가 있고, 어떤 값이 어떻게 저장되었는지 추측만 할 수 있겠죠.

하지만 그렇다고 해서 프로토타입이 왜 필요한지를 이해할 수 있다는 것은 아닙니다.

어차피 함수도 결국은 컴파일해야 하는 소스 파일 안에 선언되어 있을 것이니, 그 정보를 가지고 알아내면 되는 것 아닐까요?

물론, 이 방법도 가능하겠지만 그다지 효과적인 방법이라고 말하기는 어렵습니다.

컴파일러가 함수들의 선언에 대한 정보들을 탐색하는 동안에는 main( ) 함수를 컴파일할 수 없기 때문입니다.

이것보다 더 큰 문제는 함수가 존재하지 않았을 경우, 이 탐색이 시간 낭비가 될 수 있다는 겁니다.

C++는 프로그램의 소스 코드를 여러 파일로 나누어서 작성하는 기능을 지원합니다.

실제로 컴파일이 이루어질 때는 여러 개로 나뉜 소스 코드가 하나로 합쳐지는 작업을 거치죠.

이 경우, 컴파일러가 main( ) 함수를 컴파일할 때, 다른 함수 코드에 접근하지 못할 수도 있습니다.

이는 소스 코드에 사용한 함수가 다른 라이브러리에 포함되어 있을 때도 마찬가지입니다.

함수 프로토타입을 사용하지 않고 이러한 문제를 피할 수 있는 유일한 방법은 함수가 최초로 사용되기 전에 함수를 선언하는 것뿐이죠.

하지만 이 방법이 언제나 유효하지 않다는 것이 진짜 문제입니다.

또한 C++ 프로그래밍 스타일에서는 main( ) 함수가 항상 최상단에 위치하도록 권장하고 있습니다.

이는 어떤 프로그램이든지 간에, 그 프로그램이 실행되는 첫 시작 지점이 항상 main( ) 함수이기 때문이죠.

이는 Java, C#, Python 같은 다른 언어에서도 마찬가지입니다.

이처럼 프로토타입이 컴파일러에게 도움이 된다면, 프로그래머에게는 어떤 도움이 될까요?

프로토타입의 가장 결정적인 도움은 프로그램 에러를 줄이는데 큰 역할을 한다는 것입니다.

컴파일러가 함수의 반환 값을 정확하게 제어할 수 있게 되며, 여러분이 함수의 인자를 정확하게 작성하였는지를 확인할 수도 있죠.

만약 그렇지 않다면 컴파일러는 즉각 에러를 발생시킬 것입니다.

 


 


수고하셨습니다!


'Dev. Study Note > C++' 카테고리의 다른 글

포인터와 배열, 포인터 산술  (0) 2024.05.18
포인터 기초 개념과 new 키워드  (0) 2024.05.13
상속의 타입  (0) 2024.02.13
2D Array Row, Column  (0) 2024.01.23
friend 키워드  (0) 2024.01.10
Comments