C

C / 포인터와 함수

발아현미 2025. 4. 20. 17:13

 C에서는 헤더 파일에 존재하는 함수 말고도 사용자가 직접 함수를 만들어 사용할 수 있다. 아래 방법을 따르면 당신도 함수를 만들 수 있다.

#include <stdio.h>

int add(int a, int b) {
	printf("add함수 실행\n");
	return a + b;
}

int main() {
	int x = 3, y = 4;

	printf("%d + %d = %d", x, y, add(x, y));
	return 0;
}
  • 함수명
     함수를 정의할 때 함수명을 정해주어야 한다. 이후 함수를 호출하고 싶을 때 함수명을 통해 호출하면 된다. 
  • 매개변수
     함수 안에서 값이 바뀔 매개변수이다. 매개변수의 개수도 사용자가 지정할 수 있고, 매개변수의 변수타입 또한 지정 가능하다. 심지어 포인터 변수도 가능하다. 
     이때 매개변수 선언된 변수의 변수명은 함수 정의 과정에서만 사용되고, 실질적인 메모리 할당은 되지 않는다 (함수 내에서 정적 변수 선언이 아닌 이상) 
  • 반환값
     return값을 의미한다. 이때 return ____; 라고 코드를 작성하는데, 변수타입이 함수선언시의 리턴 변수타입과 동일해야 한다. 위 코드처럼 int add()라고 정의했으므로 return 값 또한 int type여야 한다.
  • 함수 코드
     사용자가 원하는 코드를 선언할 수 있다. 이때 매개변수 뿐만 아니라 printf, scanf도 사용 가능할 뿐만 아니라 전역변수, 정적변수 또한 선언 가능하다. 하지만 매개변수같은 경우 함수가 return값 반환 후 종료될 때 동일하게 소멸된다.

- 포인터를 반환하는 함수 vs 함수의 포인터

 배열포인터 vs 포인터배열 처럼 머리아파 보이지만, 그 문제보다는 쉬우니까 걱정하지 않아도 된다.

아래 두 코드의 차이를 알아보자.

  • 포인터를 반환하는 함수
int* f(int a, int b){
	static int count = 0;
	count++;
	
	return &count;
}

 먼저 함수를 읽어보자. f라는 함수는 int type변수 2개를 매개변수로 하고, int pointer type을 변환한다. 간략하게 함수의 용도를 얘기해보자면, f함수가 실행된 횟수를 알아보는 것이다. count변수는 정적 변수로 프로그램이 끝날 때까지 삭제되지 않는 변수이다. 하지만 함수 내에서 선언된, 지역변수이기 때문에 main함수에서는 그저 변수명만으로 접근이 불가능하다. 따라서 포인터값을 받아와야 하는데, 이 문제를 return값을 통해 해결할 수 있는 것이다. 

  • 함수의 포인터
#include <stdio.h>

void year2022() {
	int age = 19;
	printf("나이는 %d세\n", age);
}
void year2023() {
	int age = 20;
	printf("나이는 %d세\n", age);
}
void year2024() {
	int age = 21;
	printf("나이는 %d세\n", age);
}

void main() {
	void (*funcPtr[3])() = { year2022, year2023, year2024 };

	for (int i = 0; i < sizeof(funcPtr) / sizeof(*funcPtr); i++) {
		funcPtr[i]();
	}
	return 0;
}

main함수의 배열을 살펴보자. 바깥쪽부터 살펴보면 저 배열은 '매개변수는 존재하지 않고 반환값은 void인 함수'를 원소를 갖는다. 그 배열은 3의 크기를 가지고, 각 배열은 포인터 변수이다... 정리하자면, funcPtr이란 변수는 3칸을 갖고, 각 원소는 '매개변수 존재하지 않고 반환값은 void인 함수'의 포인터값을 저장하는 포인터 배열인 것이다.