Skip to main content

[C++ Primer Plus] Chapter 7. 함수

C++ 기초 플러스 책을 읽고 공부한 노트입니다.




함수 #

double Solution(int);     // 원형

Solution(num);            // 호출

double Solution(int num)  // 정의
{ 
    return num * 3.0f 
}



함수의 원형이 필요한 이유 #

  • 함수의 원형은 컴파일러에게 함수의 인터페이스를 알려준다. 즉, 리턴값과 매개변수의 데이터형을 알려준다.
  • 함수는 자신의 리턴값을 CPU의 지정된 레지스터/메모리에 복사한다. 어떤 형의 값인지는 자신의 정의를 본다.
  • 호출한 함수가 그 위치에서 값을 꺼내온다. 함수 원형을 보면 리턴값이 뭔지 알 수 있으므로 컴파일러는 그 위치에서 몇 바이트를 꺼내야 하는 지 알고 있다.



함수 원형의 매개변수 #

double Solution(int);   // 매개변수 이름을 생략해도 된다.
double Solution(...);     // 매개변수 리스트가 무엇인지 확인하지 않겠다는 뜻이다. 
double Solution(int x);

Solution(5); 
// 5 = 실제 매개변수 = 함수에 전달되는 값 = argument
// x = 형식 매개변수 = 전달되는 값을 넘겨받는데 쓰는 변수 = parameter
// 매개변수란 argument가 parameter에 대입되는 것이다. 



배열 매개변수 #

int nums [3] = {1, 2, 3};

Solution(nums, 3);

void Solution(int arr [] , int size);     
void Solution(int * arr , int size);   // 같은 의미이다. 


// 이렇게 할 수도 있다.
Solution(nums, nums + 3);

void Solution(int * begin, int * end)  


cout << sizeof(nums) << endl; // 12. 배열 전체의 크기.
cout << sizeof(arr) << endl;  //  4. 포인터 변수의 크기.
// 따라서 매개변수로 배열의 크기를 넘겨주려면 따로 추가적인 매개변수가 필요하다.


// 배열의 값을 변경하는 걸 원하지 않으면 const로 선언해준다. 
void Solution(const int arr []);



포인터와 const #

표기 ptr = &other; *ptr = 3; 의미
const int * ptr O X ptr을 이용해서 num의 값 변경 불가.
int * const ptr X O ptr이 가리키는 값을 변경 불가.
int num1 = 5;

const int * ptr = &num1; // 만약 num이 const라면 ptr은 무조건 const여야 한다. 

int num2 = 3;
ptr = &num2 // (O) ptr에 새로운 val이라는 값을 가리키게 할 수는 있다. 

*ptr = 3;  // (X) 하지만 ptr을 이용해서 그 값 자체를 바꿀 수는 없다.
int num1 = 5;

int * const ptr = &num1; 
 
*ptr = 3; // (O) num의 값을 변경할 수는 있다. 

int num2 = 3;
ptr = &num2; // (X) 하지만 ptr을 이용해서 다른 값을 가리키게 할 수는 없다.



2차원 배열 매개변수의 전달 #

  • 배열 포인터
// 포인터다. 4개의 int형 원소들을 가지고 있는 배열을 지시하는 포인터다. 
int (*arr) [4];
int arr[][4];

  • 포인터 배열
// 배열이다. 4개의 int형 포인터들을 가지고 있는 배열이다. 
int *arr [4];
  • arr[3][4] == *(*(arr + 3) + 4)
  • arr[3] == *(arr + 3)
    • 4개의 원소를 가지고 있는 3번째 행 배열의 이름이다. (sizeof(arr[3])하면 16바이트)



C스타일 문자열의 전달 #

void Solution(const char * str);   // 문자열은 마지막이 널문자이므로 배열 크기를 넘길 필요가 없다.

char name[4] = "Kim";
Solution(name);

char * nik = "KeKe";
Solution(nik);



구조체, string의 전달 #

  • 일반 변수처럼 값으로 전달된다.



array 객체의 전달 #

std::array<double, 4> expenses;
Solution(expenses);


void Solution(std::array<double, 4> * exp)
{  
    cout << (*exp)[0] << endl; 
}

// exp는 포인터다. 
// *exp는 객체이다. 
// (*exp)[0] 은 그 객체에 있는 원소이다. 



함수 포인터의 전달 #

double Function(int num);

// pf는 함수를 지시하는 포인터, *pf는 함수 자체.

// 함수 포인터
void Solution(double (*pf) (int))
{  
    double result = pf(5);       // (*pf)(5)
}

// 함수 포인터들의 배열
void Solution(double (*pf [3]) (int))
{  
    double result = pf[0](5);    // (*pf[0])(5)
} 

// 함수 포인터의 포인터
void Solution(double (**pf) (int))
{  
    double result = pf[0](5);    // (*pf[0])(5)
}

// 함수 포인터들의 배열의 포인터
void Solution(double (*(*pf) [3]) (int))
{  
    double result = (*pf)[0](5); // (*(*pf)[0])(5)
}


// pf를 함수 포인터형으로 쓸 수 있다. 
typedef double (*pf) (int);
pf function = f1;