工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Industrial programming >> C言語

例を使用した C プログラミングの関数ポインター

ポインターは、1 つの値を返すように制限されている「C」関数に大きな可能性をもたらします。ポインター パラメーターを使用することで、関数はデータのコピーではなく実際のデータを処理できるようになりました。
変数の実際の値を変更するために、呼び出しステートメントはアドレスを関数内のポインター パラメーターに渡します。
チュートリアル、あなたは学びます-

関数ポインタの例

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

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

<オール>
  • 2 つの変数値を交換する関数を宣言します。この関数は、2 つの整数ポインターをパラメーターとして受け取り、呼び出されたときに任意の値を返します。
  • メイン関数では、2 つの整数変数 (「m」と「n」) を宣言して初期化し、それぞれの値を出力します。
  • アンパサンド記号を使用して、2 つの変数のアドレスを引数として渡すことにより、swap() 関数を呼び出します。その後、変数の新しいスワップ値を出力します。
  • ここでは、パラメータとして 2 つの整数変数アドレスを受け取る swap() 関数の内容を定義し、2 番目の変数に配置される値変数の 1 つを保存するための 3 番目のストレージ ボックスとして使用される一時的な整数変数を宣言します。
  • 「a」が指す最初の変数の内容を一時変数に保存します。
  • b が指す 2 番目の変数を、a が指す最初の変数に格納します。
  • 一時変数に保存された最初の変数の値で、2 番目の変数 (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] 表記を使用)、要素配列全体を反復した後に返されるローカル変数に合計を蓄積します。
  • 5 つの整数要素を持つ整数配列を宣言して初期化します。配列名 (アドレスとして機能) と配列サイズを 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
    

    ここで、プログラムの詳細について説明します

    <オール>
  • 整数値を含む配列アドレスを返し、引数を取らない関数を定義して宣言します。
  • 関数が呼び出された後に構築された完全な配列を受け取る整数ポインタを宣言し、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
    

    <オール>
  • 関数が呼び出されたときに、パラメーターで指定された k 回 Hi テキストを出力する標準関数を定義して宣言します
  • 整数パラメータを取り、何も返さないポインタ関数を (特別な宣言で) 定義します。
  • ポインター関数を Hi_function で初期化します。つまり、ポインターは Hi_function() を指します。
  • 関数名に引数を付けて呼び出す標準的な関数呼び出しではなく、引数として数値 3 を渡してポインター関数のみを呼び出します。それだけです!
  • 関数名は、最初の要素を指す配列名のように、実行可能コードの開始アドレスを指すことに注意してください。したがって、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

    ここでは、プログラムの詳細について説明します:

    <オール>
  • 2 つの整数引数を取り、整数値を返す 4 つの関数を宣言および定義します。これらの関数は、ユーザーが呼び出す関数に関する 2 つの引数を加算、減算、乗算、および除算します。
  • オペランド、演算タイプ、および結果をそれぞれ処理するために、4 つの整数を宣言します。また、4 つの関数ポインターの配列を宣言します。配列要素の各関数ポインタは、2 つの整数パラメータを取り、整数値を返します。
  • すでに宣言されている関数を使用して、各配列要素を割り当てて初期化します。たとえば、3 番目の関数ポインタである 3 番目の要素は、乗算演算関数を指します。
  • ユーザーがキーボードで入力したオペランドと操作の種類を求めます。
  • 適切な配列要素 (関数ポインタ) を引数で呼び出し、適切な関数によって生成された結果を保存します。
  • 命令 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

    ここでは、プログラムの詳細について説明します:

    <オール>
  • 整数値を返し、特定のデータ型のない変更不可能な変数のアドレスを取る関数を定義して宣言します。 num ポインターが指すコンテンツ変数 (x) のキューブ値を計算します。これは void ポインターであるため、特定の表記 (* データ型) ポインターを使用して整数データ型に型キャストする必要があり、戻りますキューブ値
  • オペランドと結果変数を宣言します。また、オペランドを値「4」で初期化します。
  • オペランド アドレスを渡してキューブ関数を呼び出し、戻り値を結果変数で処理します
  • 引数としての関数ポインタ

    関数ポインターを別の関数に引数として渡すことで、関数ポインターを悪用するもう 1 つの方法は、受信関数が「コールバックする」ため、「コールバック関数」と呼ばれることもあります。
    stdlib.h ヘッダー ファイルでは、Quicksort の「qsort() 」関数は、配列のソート専用のアルゴリズムであるこの手法を使用します。

    void qsort(void *base, size_t num, size_t width, int (*compare)(const void *, const void *))

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

    ここでは、プログラムの詳細について説明します:

    <オール>
  • 2 つの引数で構成される比較関数を定義し、引数が同じ値の場合は 0 を返し、arg1 が arg2 の前にある場合は <0 を返し、arg1 が arg2 の後にある場合は>0 を返します。配列データ型 (整数)
  • 整数配列を定義して初期化します 配列サイズは num に格納されます 変数であり、各配列要素のサイズは、事前定義された C 演算子 sizeof() を使用して width 変数に格納されます。
  • qsort と呼びます 関数を呼び出して、ユーザーが以前に定義した配列名、サイズ、幅、および比較関数を渡して、配列を昇順で並べ替えます。比較は、配列全体が並べ替えられるまで、各反復で 2 つの配列要素を取得することによって実行されます。
  • 配列要素を出力して、for ループを使用して配列全体を反復することにより、配列が適切にソートされるようにします。

  • C言語

    1. C プログラミングにおけるユーザー定義関数のタイプ
    2. C++ do…while ループと例
    3. C++ ポインタと例
    4. C++ 演算子のオーバーロードと例
    5. C++ 関数とプログラム例
    6. 例を含む C# コレクションのチュートリアル
    7. C のポインター:C プログラミングのポインターとは何ですか?種類
    8. 例を使用した Python 文字列 count()
    9. 例を含む Python Lambda 関数
    10. 例を使用した Python round() 関数
    11. 例を使用した Python map() 関数