C プログラミングの関数ポインターと例

ポインタは、XNUMX つの値を返すように制限されている 'C' 関数に大きな可能性を与えます。 ポインター パラメーターを使用すると、関数はデータのコピーではなく実際のデータを処理できるようになりました。

変数の実際の値を変更するには、呼び出しステートメントで関数内のポインター パラメーターにアドレスを渡します。

関数ポインタの例

たとえば、次のプログラムは XNUMX の 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

関数ポインタの例

関数はアドレスによって変数にアクセスするため、プログラムは実際の変数値を交換します。 ポインタ。 ここではプログラムのプロセスについて説明します。

  1. XNUMX つの変数値を交換する関数を宣言します。この関数は XNUMX つの整数ポインターをパラメーターとして受け取り、呼び出されたときに任意の値を返します。
  2. main 関数では、XNUMX つの整数変数 ('m' と 'n') を宣言して初期化し、それぞれの値を出力します。
  3. アンパサンド記号を使用して XNUMX つの変数のアドレスを引数として渡し、swap() 関数を呼び出します。 その後、変数の新しく交換された値を出力します。
  4. ここでは、XNUMX つの整変数アドレスをパラメータとして受け取る swap() 関数の内容を定義し、XNUMX 番目のストレージとして使用される一時整数変数を宣言します。 box XNUMX 番目の変数に代入される値変数の XNUMX つを保存します。
  5. 「a」が指す最初の変数の内容を一時変数に保存します。
  6. b が指す XNUMX 番目の変数を、a が指す最初の変数に格納します。
  7. 一時変数に保存された最初の変数の値で XNUMX 番目の変数 (b で指定) を更新します。

配列パラメータを持つ関数

C では、配列を値で関数に渡すことはできません。 一方、配列名はポインタ (アドレス) であるため、配列名を関数に渡すだけで、これは配列へのポインタを渡すことを意味します。

たとえば、次のように考えます。wing プログラム:

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

ここでは、プログラムコードをde付きで説明します。tails

配列パラメータを持つ関数

  1. add_array() 関数を宣言して定義します。この関数は、配列アドレス (ポインタ) とその要素番号をパラメータとして受け取り、これらの要素の累積合計を返します。 ポインタは配列要素を反復するために使用され (p[k] 表記を使用)、要素配列全体を反復した後に返されるローカル変数に合計を蓄積します。
  2. XNUMX つの整数要素を含む整数配列を宣言して初期化します。 配列名 (アドレスとして機能します) と配列サイズを add_array()関数を引数として呼び出します。

配列を返す関数

C では、次のように配列へのポインタを返すことができます。wing プログラム:

#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

ここでは、プログラムについて説明します。tails

配列を返す関数

  1. 整数値を含む配列アドレスを返し、引数をとらない関数を定義して宣言します。
  2. 関数の呼び出し後に構築された完全な配列を受け取る整数ポインターを宣言し、XNUMX つの要素の配列全体を反復してその内容を出力します。

関数によって返される配列アドレスを格納するために、配列ではなくポインターが定義されていることに注意してください。 また、ローカル変数が関数から返されるときは、関数内でそれを static として宣言する必要があることに注意してください。

関数ポインタ

定義により、ポインタはメモリ内の任意の場所のアドレスを指すことがわかっていますが、メモリ内の関数として実行可能コードの先頭を指すこともできます。
関数へのポインターは * で宣言されます。その宣言の一般的なステートメントは次のとおりです。

return_type (*function_name)(arguments)

(*function_name) を囲む括弧が重要であることに注意してください。括弧がないと、コンパイラーは function_name が return_type のポインターを返しているとみなしてしまうからです。
関数ポインターを定義したら、それを関数に割り当てる必要があります。 たとえば、次のプログラム宣言は、ares 通常の関数では、関数ポインタを定義し、その関数ポインタを通常の関数に割り当て、その後、ポインタを介して関数を呼び出します。

#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

C の関数ポインター

  1. 関数が呼び出されたときに、パラメーターで示される Hi テキストを k 回出力する標準関数を定義して宣言します。
  2. 整数パラメーターを受け取り、何も返さないポインター関数を (特別な宣言を使用して) 定義します。
  3. ポインター関数を Hi_function で初期化します。これは、ポインターが Hi_function() を指すことを意味します。
  4. 関数名に引数を付けて呼び出す標準の関数ではなく、数値 3 を引数として渡してポインタ関数のみを呼び出します。それだけです。

関数名は、最初の要素を指す配列名と同様に、実行可能コードの先頭アドレスを指すことに注意してください。 したがって、function_ptr = &Hi_function や (*funptr)(3) のような命令は正しいです。
注: アドレスを挿入することは重要ではありません。 operator & および間接指定 operator * 関数代入および関数呼び出し中。

関数ポインタの配列

次のプログラムのように、関数ポインターの配列は、意思決定を行うためのスイッチまたは 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

ここでは、プログラムについて説明します。tails:

関数ポインタの配列

  1. XNUMX つを宣言し、定義します。 機能 これは XNUMX つの整数引数を受け取り、整数値を返します。 これらの関数は、ユーザーがどの関数を呼び出しているかに関する XNUMX つの引数を加算、減算、乗算、除算します。
  2. 処理する 4 つの整数を宣言します operaNDS、 operaそれぞれ、タイプと結果を示します。また、4 つの関数ポインターの配列を宣言します。配列要素の各関数ポインタは 2 つの整数パラメータを受け取り、整数値を返します。
  3. すでに宣言されている関数を使用して各配列要素を割り当てて初期化します。たとえば、3 番目の関数ポインタである 3 番目の要素は乗算を指します。 operaション機能。
  4. 我々が求めて operaNDSと種類 operaユーザーがキーボードで入力したものです。
  5. 引数を指定して適切な配列要素 (関数ポインタ) を呼び出し、適切な関数によって生成された結果を保存します。

命令 int (*ope[4])(int, int); 関数ポインタの配列を定義します。 各配列要素は同じパラメータと戻り値の型を持つ必要があります。
ステートメント result = ope[choice](x, y); ユーザーの選択に従って、適切な関数を実行します。入力された XNUMX つの整数は、関数に渡される引数です。

void ポインターを使用する関数

Void ポインターは関数宣言中に使用されます。 void * 戻り型を使用すると、任意の型を返すことができます。 関数に渡すときにパラメーターが変更されないと仮定する場合は、それを const として宣言します。
例:

 void * cube (const void *);

以下を検討してくださいwing プログラム:

#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

ここでは、プログラムについて説明します。tails:

void ポインターを使用する関数

  1. 整数値を返し、特定のデータ型を持たない変更不可能な変数のアドレスを取得する関数を定義して宣言します。 num ポインターが指すコンテンツ変数 (x) の cube 値を計算します。これは void ポインターであるため、特定の表記法 (* datatype) ポインターを使用して整数データ型に型キャストする必要があり、次の値を返します。立方体の値。
  2. 私たちは宣言します operand と結果変数。また、初期化します operand の値は「4」です。
  3. を渡して cube 関数を呼び出します。 operand アドレスを指定し、結果変数の戻り値を処理します。

引数としての関数ポインタ

関数ポインタを別の関数に引数として渡すことで関数ポインタを悪用するもう XNUMX つの方法は、受信関数がそれを「コールバックする」ため、「コールバック関数」と呼ばれることもあります。
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 つの引数で構成される関数ポインター。引数の値が同じ場合は 0 を返し、arg1 が arg2 の前に来る場合は <0 を返し、arg1 が arg2 の後に来る場合は >XNUMX を返します。

次のことwing プログラムは、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

ここでは、プログラムについて説明します。tails:

引数としての関数ポインタ

  1. 0 つの引数で構成される比較関数を定義し、引数が同じ値を持つ場合は 0 を返し、arg1 が arg2 の前に来る場合は <0、arg1 が arg2 の後に来る場合は >XNUMX を返します。パラメータは、適切な配列データ型にキャストされた void ポインター型です。 (整数)
  2. 整数配列を定義して初期化します。配列サイズは NUM 変数と各配列要素のサイズは、事前定義された sizeof() を使用して width 変数に格納されます。 C operaタ.
  3. 我々は呼ぶ クイックソート 関数を作成し、配列を昇順に並べ替えるために、ユーザーが以前に定義した配列名、サイズ、幅、および比較関数を渡します。 比較は、配列全体がソートされるまで、各反復で XNUMX つの配列要素を取り込むことによって実行されます。
  4. 配列要素を出力して、配列全体を反復処理して配列が適切にソートされていることを確認します。 forループ.