예제가 포함된 C 프로그래밍의 함수 포인터
포인터는 하나의 값을 반환하도록 제한되는 'C' 함수에 큰 가능성을 제공합니다. 포인터 매개변수를 사용하면 이제 우리 함수는 데이터 복사본이 아닌 실제 데이터를 처리할 수 있습니다.
변수의 실제 값을 수정하기 위해 호출 문은 주소를 함수의 포인터 매개 변수에 전달합니다.
함수 포인터 예
예를 들어, 다음 프로그램은 두 값을 XNUMX로 바꿉니다.
void swap (int *a, int *b); int main() { int m = 25; int n = 100; printf("m is %d, n is %d\n", m, n); swap(&m, &n); printf("m is %d, n is %d\n", m, n); return 0;} void swap (int *a, int *b) { int temp; temp = *a; *a = *b; *b = temp;} }
출력:
m is 25, n is 100 m is 100, n is 25
함수는 다음을 사용하여 주소로 변수에 액세스하기 때문에 프로그램은 실제 변수 값을 교환합니다. 포인터. 여기서 우리는 프로그램 프로세스에 대해 논의할 것입니다:
- 두 개의 변수 값을 교환하는 함수를 선언합니다. 이 함수는 두 개의 정수 포인터를 매개 변수로 사용하고 호출 시 모든 값을 반환합니다.
- 메인 함수에서는 두 개의 정수 변수('m'과 'n')를 선언하고 초기화한 다음 각각의 값을 인쇄합니다.
- 앰퍼샌드 기호를 사용하여 두 변수의 주소를 인수로 전달하여 swap() 함수를 호출합니다. 그 후, 새로 교체된 변수 값을 인쇄합니다.
- 여기서는 두 개의 정수 변수 주소를 매개변수로 받는 swap() 함수 내용을 정의하고, 두 번째 변수에 들어갈 값 변수 중 하나를 저장하는 세 번째 저장 상자로 사용되는 임시 정수 변수를 선언합니다.
- 'a'가 가리키는 첫 번째 변수의 내용을 임시변수에 저장합니다.
- b가 가리키는 두 번째 변수를 a가 가리키는 첫 번째 변수에 저장합니다.
- 임시 변수에 저장된 첫 번째 변수의 값으로 두 번째 변수(b가 가리키는)를 업데이트합니다.
배열 매개변수가 있는 함수
C에서는 배열을 값으로 함수에 전달할 수 없습니다. 반면 배열 이름은 포인터(주소)이므로 배열 이름을 함수에 전달하면 배열에 대한 포인터를 전달한다는 의미입니다.
예를 들어, 다음 프로그램을 고려해 보겠습니다.
int add_array (int *a, int num_elements); int main() { int Tab[5] = {100, 220, 37, 16, 98}; printf("Total summation is %d\n", add_array(Tab, 5)); return 0;} int add_array (int *p, int size) { int total = 0; int k; for (k = 0; k < size; k++) { total += p[k]; /* it is equivalent to total +=*p ;p++; */} return (total);}
출력:
Total summation is 471
여기서는 프로그램 코드와 그 세부 사항을 설명하겠습니다.
- 우리는 요소 번호가 포함된 배열 주소(포인터)를 매개 변수로 사용하고 이러한 요소의 총 누적 합계를 반환하는 add_array() 함수를 선언하고 정의합니다. 포인터는 배열 요소를 반복하는 데 사용되며(p[k] 표기법 사용) 전체 요소 배열을 반복한 후 반환될 로컬 변수에 합계를 누적합니다.
- XNUMX개의 정수 요소가 있는 정수 배열을 선언하고 초기화합니다. 배열 이름(주소 역할)과 배열 크기를 전달하여 총 합계를 인쇄합니다. add_array()함수를 인수로 호출합니다.
배열을 반환하는 함수
C에서는 다음 프로그램과 같이 배열에 대한 포인터를 반환할 수 있습니다.
#include <stdio.h> int * build_array(); int main() { int *a; a = build_array(); /* get first 5 even numbers */ for (k = 0; k < 5; k++) printf("%d\n", a[k]); return 0;} int * build_array() { static int Tab[5]={1,2,3,4,5}; return (Tab);}
출력:
1 2 3 4 5
여기서 우리는 프로그램 세부 사항을 논의할 것입니다
- 정수 값을 포함하고 인수를 취하지 않은 배열 주소를 반환하는 함수를 정의하고 선언합니다.
- 함수가 호출된 후 작성된 전체 배열을 수신하는 정수 포인터를 선언하고 전체 XNUMX개 요소 배열을 반복하여 해당 내용을 인쇄합니다.
함수가 반환한 배열 주소를 저장하기 위해 배열이 아닌 포인터가 정의되어 있다는 점에 유의하세요. 또한 지역 변수가 함수에서 반환될 때 함수에서 이를 정적으로 선언해야 한다는 점에 유의하세요.
함수 포인터
포인터가 모든 메모리 위치의 주소를 가리킨다는 것을 정의로 알 수 있듯이 포인터는 메모리의 함수로서 실행 가능한 코드의 시작 부분을 가리킬 수도 있습니다.
함수에 대한 포인터는 * 로 선언되며 선언의 일반적인 설명은 다음과 같습니다.
return_type (*function_name)(arguments)
(*function_name) 주변의 괄호가 중요하다는 점을 기억해야 합니다. 왜냐하면 괄호가 없으면 컴파일러는 function_name이 return_type의 포인터를 반환한다고 생각할 것이기 때문입니다.
함수 포인터를 정의한 후에는 함수에 할당해야 합니다. 예를 들어, 다음 프로그램은 일반 함수를 선언하고, 함수 포인터를 정의하고, 함수 포인터를 일반 함수에 할당한 다음 포인터를 통해 함수를 호출합니다.
#include <stdio.h> void Hi_function (int times); /* function */ int main() { void (*function_ptr)(int); /* function pointer Declaration */ function_ptr = Hi_function; /* pointer assignment */ function_ptr (3); /* function call */ return 0;} void Hi_function (int times) { int k; for (k = 0; k < times; k++) printf("Hi\n");}
출력:
Hi Hi Hi
- 함수가 호출될 때 매개변수 times에 의해 표시된 Hi 텍스트를 k번 인쇄하는 표준 함수를 정의하고 선언합니다.
- 정수 매개변수를 취하고 아무것도 반환하지 않는 포인터 함수(특수 선언 포함)를 정의합니다.
- 포인터 함수를 Hi_function으로 초기화합니다. 이는 포인터가 Hi_function()을 가리킨다는 의미입니다.
- 함수 이름에 인수를 붙여 호출하는 표준 함수 대신 숫자 3을 인수로 전달하여 포인터 함수만 호출하면 됩니다!
함수 이름은 첫 번째 요소를 가리키는 배열 이름과 마찬가지로 실행 가능한 코드의 시작 주소를 가리킨다는 점을 명심하세요. 따라서 function_ptr = &Hi_function 및 (*funptr)(3)과 같은 지침이 정확합니다.
참고: 함수 할당과 함수 호출 중에 주소 연산자 &와 간접 연산자 *를 삽입하는 것은 중요하지 않습니다.
함수 포인터 배열
함수 포인터 배열은 다음 프로그램에서와 같이 결정을 내리기 위한 스위치 또는 if 문 역할을 할 수 있습니다.
#include <stdio.h> int sum(int num1, int num2); int sub(int num1, int num2); int mult(int num1, int num2); int div(int num1, int num2); int main() { int x, y, choice, result; int (*ope[4])(int, int); ope[0] = sum; ope[1] = sub; ope[2] = mult; ope[3] = div; printf("Enter two integer numbers: "); scanf("%d%d", &x, &y); printf("Enter 0 to sum, 1 to subtract, 2 to multiply, or 3 to divide: "); scanf("%d", &choice); result = ope[choice](x, y); printf("%d", result); return 0;} int sum(int x, int y) {return(x + y);} int sub(int x, int y) {return(x - y);} int mult(int x, int y) {return(x * y);} int div(int x, int y) {if (y != 0) return (x / y); else return 0;}
Enter two integer numbers: 13 48 Enter 0 to sum, 1 to subtract, 2 to multiply, or 3 to divide: 2 624
여기서는 프로그램 세부 사항에 대해 설명하겠습니다.
- 우리는 XNUMX가지를 선언하고 정의합니다. 기능 두 개의 정수 인수를 취하고 정수 값을 반환합니다. 이러한 함수는 사용자가 호출하는 함수에 관한 두 인수를 더하고, 빼고, 곱하고 나눕니다.
- 우리는 각각 피연산자, 연산 유형, 결과를 처리하기 위해 4개의 정수를 선언합니다. 또한, 우리는 XNUMX개의 함수 포인터 배열을 선언합니다. 배열 요소의 각 함수 포인터는 XNUMX개의 정수 매개변수를 취하고 정수 값을 반환합니다.
- 우리는 이미 선언된 함수로 각 배열 요소를 할당하고 초기화합니다. 예를 들어, 세 번째 함수 포인터인 세 번째 요소는 곱셈 연산 함수를 가리킬 것입니다.
- 우리는 사용자가 키보드로 입력한 피연산자와 연산 유형을 구합니다.
- 인수를 사용하여 적절한 배열 요소(함수 포인터)를 호출하고 해당 함수에 의해 생성된 결과를 저장합니다.
명령 int (*ope[4])(int, int); 함수 포인터의 배열을 정의합니다. 각 배열 요소에는 동일한 매개변수와 반환 유형이 있어야 합니다.
명령문 결과 = ope[choice](x, y); 사용자의 선택에 따라 적절한 함수를 실행합니다. 입력된 두 개의 정수는 함수에 전달되는 인수입니다.
void 포인터를 사용하는 함수
Void 포인터는 함수 선언 중에 사용됩니다. 우리는 void * 반환 유형을 사용하여 모든 유형을 반환할 수 있습니다. 함수에 전달할 때 매개변수가 변경되지 않는다고 가정하면 이를 const로 선언합니다.
예 :
void * cube (const void *);
다음 프로그램을 고려하십시오.
#include <stdio.h> void* cube (const void* num); int main() { int x, cube_int; x = 4; cube_int = cube (&x); printf("%d cubed is %d\n", x, cube_int); return 0;} void* cube (const void *num) { int result; result = (*(int *)num) * (*(int *)num) * (*(int *)num); return result;}
결과 :
4 cubed is 64
여기서는 프로그램 세부 사항에 대해 설명하겠습니다.
- 정수 값을 반환하고 특정 데이터 유형 없이 변경할 수 없는 변수의 주소를 가져오는 함수를 정의하고 선언합니다. num 포인터가 가리키는 콘텐츠 변수(x)의 큐브 값을 계산하고 void 포인터이므로 특정 표기법(* 데이터 유형) 포인터를 사용하여 정수 데이터 유형으로 타입 캐스팅하고 반환합니다. 큐브 값.
- 우리는 피연산자와 결과 변수를 선언합니다. 또한, 우리는 피연산자를 값 "4"로 초기화합니다.
- 피연산자 주소를 전달하여 cube 함수를 호출하고, result 변수에서 반환값을 처리합니다.
인수로서의 함수 포인터
함수 포인터를 수신 함수가 "콜백"하기 때문에 "콜백 함수"라고도 하는 다른 함수에 인수로 전달하여 함수 포인터를 활용하는 또 다른 방법입니다.
stdlib.h 헤더 파일에서 Quicksort "qsort()" 함수는 배열 정렬 전용 알고리즘인 이 기술을 사용합니다.
void qsort(void *base, size_t num, size_t width, int (*compare)(const void *, const void *))
- void *base : 배열에 대한 포인터가 void입니다.
- size_t num : 배열 요소 번호입니다.
- size_t width 요소 크기입니다.
- int (*compare (const void *, const void *) : 두 개의 인수로 구성된 함수 포인터로, 인수의 값이 같을 때 0을 반환하고, arg0이 arg1보다 앞에 오면 <2, arg0이 arg1 뒤에 오면 >2을 반환합니다.
다음 프로그램은 qsort() 함수를 사용하여 정수 배열을 작은 숫자에서 큰 숫자 순으로 정렬합니다.
#include <stdio.h> #include <stdlib.h> int compare (const void *, const void *); int main() { int arr[5] = {52, 14, 50, 48, 13}; int num, width, i; num = sizeof(arr)/sizeof(arr[0]); width = sizeof(arr[0]); qsort((void *)arr, num, width, compare); for (i = 0; i < 5; i++) printf("%d ", arr[ i ]); return 0;} int compare (const void *elem1, const void *elem2) { if ((*(int *)elem1) == (*(int *)elem2)) return 0; else if ((*(int *)elem1) < (*(int *)elem2)) return -1; else return 1;}
결과 :
13 14 48 50 52
여기서는 프로그램 세부 사항에 대해 설명하겠습니다.
- 두 개의 인수로 구성된 비교 함수를 정의하고 인수의 값이 같을 때 0을 반환하고, arg0이 arg1보다 앞에 오면 <2을, arg0 뒤에 arg1이 오면 >2을 반환합니다. 매개 변수는 적절한 배열 데이터 유형으로 캐스팅된 void 포인터 유형입니다. (정수)
- 정수 배열을 정의하고 초기화합니다. 배열 크기는 NUM 변수와 각 배열 요소의 크기는 미리 정의된 sizeof()를 사용하여 width 변수에 저장됩니다. C 연산자.
- 우리는 전화 큐소트 함수에 배열을 오름차순으로 정렬하기 위해 사용자가 이전에 정의한 배열 이름, 크기, 너비 및 비교 함수를 전달합니다. 비교는 전체 배열이 정렬될 때까지 각 반복에서 두 개의 배열 요소를 가져와 수행됩니다.
- 다음을 사용하여 전체 배열을 반복하여 배열이 잘 정렬되었는지 확인하기 위해 배열 요소를 인쇄합니다. for 루프.