例を使用した C プログラミングの関数ポインター
ポインターは、1 つの値を返すように制限されている「C」関数に大きな可能性をもたらします。ポインター パラメーターを使用することで、関数はデータのコピーではなく実際のデータを処理できるようになりました。
変数の実際の値を変更するために、呼び出しステートメントはアドレスを関数内のポインター パラメーターに渡します。
チュートリアル、あなたは学びます-
- 関数ポインタの例
- 配列パラメータを持つ関数
- 配列を返す関数
- 関数ポインタ
- 関数ポインタの配列
- void ポインタを使用する関数
- 引数としての関数ポインタ
関数ポインタの例
たとえば、次のプログラムは 2 つの値を 2 つ交換します:
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
関数はポインターを使用してアドレスで変数にアクセスするため、プログラムは実際の変数値をスワップします。ここでは、プログラムのプロセスについて説明します:
<オール>配列パラメータを持つ関数
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
ここでは、プログラムコードとその詳細について説明します
<オール>
配列を返す関数
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
ここで、プログラムの詳細について説明します
<オール>
関数によって返される配列アドレスを格納するために、配列ではなくポインターが定義されていることに注意してください。また、ローカル変数が関数から返される場合、関数内で static として宣言する必要があることに注意してください。
関数ポインタ
定義により、ポインターは任意のメモリ位置のアドレスを指すことがわかっているため、メモリ内の関数として実行可能コードの先頭を指すこともできます。
関数へのポインターは、* の一般的なステートメントで宣言されます。その宣言は:
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
<オール>
関数名は、最初の要素を指す配列名のように、実行可能コードの開始アドレスを指すことに注意してください。したがって、function_ptr =&Hi_function や (*funptr)(3) などの命令は正しいものです。
注:関数の代入と関数の呼び出し中に、アドレス演算子 &と間接演算子 * を挿入することは重要ではありません。
関数ポインタの配列
関数ポインターの配列は、次のプログラムのように、決定を行うための switch または 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
ここでは、プログラムの詳細について説明します:
<オール>
命令 int (*ope[4])(int, int);関数ポインターの配列を定義します。各配列要素は、同じパラメータと戻り値の型を持つ必要があります。
ステートメント result =ope[choice](x, y);ユーザーの選択に従って適切な関数を実行します 入力された 2 つの整数は、関数に渡される引数です。
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
ここでは、プログラムの詳細について説明します:
<オール>
引数としての関数ポインタ
関数ポインターを別の関数に引数として渡すことで、関数ポインターを悪用するもう 1 つの方法は、受信関数が「コールバックする」ため、「コールバック関数」と呼ばれることもあります。
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 *) :2 つの引数で構成される関数ポインターで、引数が同じ値の場合は 0 を返し、arg1 が arg2 の前にある場合は <0 を返し、arg1 が arg2 の後にある場合は>0 を返します。 .
次のプログラムは、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
ここでは、プログラムの詳細について説明します:
<オール>
C言語