Bagaimana saya bisa menggunakan array pointer fungsi?

150

Bagaimana saya harus menggunakan array pointer fungsi di C?

Bagaimana saya bisa menginisialisasi mereka?

The Guy with The Hat
sumber

Jawaban:

194

Anda memiliki contoh yang baik di sini (Array of Function pointer) , dengan sintaksis yang terinci .

int sum(int a, int b);
int subtract(int a, int b);
int mul(int a, int b);
int div(int a, int b);

int (*p[4]) (int x, int y);

int main(void)
{
  int result;
  int i, j, op;

  p[0] = sum; /* address of sum() */
  p[1] = subtract; /* address of subtract() */
  p[2] = mul; /* address of mul() */
  p[3] = div; /* address of div() */
[...]

Untuk memanggil salah satu dari pointer fungsi tersebut:

result = (*p[op]) (i, j); // op being the index of one of the four functions
VONC
sumber
3
Jawaban yang bagus - Anda harus mengembangkannya untuk menunjukkan cara memanggil salah satu fungsi.
Jonathan Leffler
1
@crucifiedsoul "the C Programming Language" yang ditulis oleh Brian Kernighan dan Dennis Ritchie? Bisa jadi, tetapi saya tidak memilikinya sebagai referensi pada saat saya menulis jawaban tiga setengah tahun yang lalu. Jadi saya tidak tahu.
VonC
12
Saya ingin menambahkan Anda dapat menginisialisasi p dengan(*p[4]) (int, int) {sum,substract,mul,div}
jiggunjer
1
@VonC: jawaban yang bagus. +1 untuk tautan.
Destructor
@ jiggunjer s / kurangi / kurangi /: p. Tapi terima kasih atas komentarnya, sangat berguna :). +1.
RastaJedi
41

Jawaban di atas dapat membantu Anda tetapi Anda mungkin juga ingin tahu cara menggunakan array fungsi pointer.

void fun1()
{

}

void fun2()
{

}

void fun3()
{

}

void (*func_ptr[3])() = {fun1, fun2, fun3};

main()
{
    int option;


    printf("\nEnter function number you want");
    printf("\nYou should not enter other than 0 , 1, 2"); /* because we have only 3 functions */
    scanf("%d",&option);

    if((option>=0)&&(option<=2))
    { 
        (*func_ptr[option])();
    }

    return 0;
}

Anda hanya bisa menetapkan alamat fungsi dengan tipe pengembalian yang sama dan tipe argumen yang sama dan tanpa argumen ke array penunjuk fungsi tunggal.

Anda juga bisa memberikan argumen seperti di bawah ini jika semua fungsi di atas memiliki jumlah argumen yang sama.

  (*func_ptr[option])(argu1);

Catatan: di sini dalam array penomoran pointer fungsi akan mulai dari 0 sama seperti pada array umum. Jadi dalam contoh di atas fun1dapat dipanggil jika opsi = 0, fun2dapat dipanggil jika opsi = 1 dan fun3dapat dipanggil jika opsi = 2.

Keraguan Manoj
sumber
Bahkan untuk demo kecil ini, Anda harus menambahkan tanda centang untuk nilai input, karena kode menargetkan pemula ... :-)
PhiLho
if ((option <0) || (option> 2)) {(* func_ptr [option]) (); } Bung ini berarti metode ini dipanggil hanya ketika pengguna mengetikkan indeks yang tidak valid!
ljs
6
Itu adalah jawaban yang baik, namun Anda harus menambahkan tanda kurung setelah (* func_ptr [3]) untuk membuatnya menjadi kode yang valid.
Alex
Ini adalah jawaban yang sangat buruk. Karena tanda kurung yang hilang, kode ini bahkan tidak dapat dikompilasi .
CL.
seperti @Alex berkata, ubah saja dari (*func_ptr[3])menjadi (*func_ptr[3])()dan itu akan dikompilasi
dsaydon
9

Inilah cara Anda dapat menggunakannya:

New_Fun.h

#ifndef NEW_FUN_H_
#define NEW_FUN_H_

#include <stdio.h>

typedef int speed;
speed fun(int x);

enum fp {
    f1, f2, f3, f4, f5
};

void F1();
void F2();
void F3();
void F4();
void F5();
#endif

New_Fun.c

#include "New_Fun.h"

speed fun(int x)
{
    int Vel;
    Vel = x;
    return Vel;
}

void F1()
{
    printf("From F1\n");
}

void F2()
{
    printf("From F2\n");
}

void F3()
{
    printf("From F3\n");
}

void F4()
{
    printf("From F4\n");
}

void F5()
{
    printf("From F5\n");
}

Main.c

#include <stdio.h>
#include "New_Fun.h"

int main()
{
    int (*F_P)(int y);
    void (*F_A[5])() = { F1, F2, F3, F4, F5 };    // if it is int the pointer incompatible is bound to happen
    int xyz, i;

    printf("Hello Function Pointer!\n");
    F_P = fun;
    xyz = F_P(5);
    printf("The Value is %d\n", xyz);
    //(*F_A[5]) = { F1, F2, F3, F4, F5 };
    for (i = 0; i < 5; i++)
    {
        F_A[i]();
    }
    printf("\n\n");
    F_A[f1]();
    F_A[f2]();
    F_A[f3]();
    F_A[f4]();
    return 0;
}

Saya harap ini membantu dalam memahami Function Pointer.

Rasmi Ranjan Nayak
sumber
Baris 15 dari Main.c harus untuk (i = 0; i <5; i ++), kan?
user3116936
Mengapa Anda mendeklarasikan pencacah fp?
Atur
@Arrrow: Saya pikir saya melihat beberapa kode warisan di mana mereka membuatnya dengan cara itu ... Dan itu terlihat sangat indah. Hapus f1, f2 ...dan ganti 'writefile, readfromfile ...' ... itu menjadi lebih dapat redable
Rasmi Ranjan Nayak
5

"Jawaban" ini lebih merupakan tambahan dari jawaban VonC; hanya mencatat bahwa sintaks dapat disederhanakan melalui typedef, dan inisialisasi agregat dapat digunakan:

typedef int FUNC(int, int);

FUNC sum, subtract, mul, div;
FUNC *p[4] = { sum, subtract, mul, div };

int main(void)
{
    int result;
    int i = 2, j = 3, op = 2;  // 2: mul

    result = p[op](i, j);   // = 6
}

// maybe even in another file
int sum(int a, int b) { return a+b; }
int subtract(int a, int b) { return a-b; }
int mul(int a, int b) { return a*b; }
int div(int a, int b) { return a/b; }
MM
sumber
2

Oh, ada banyak contoh. Lihat saja apa saja di dalam glib atau gtk. Anda dapat melihat pekerjaan pointer fungsi bekerja di sana sepanjang jalan.

Di sini misal inisialisasi barang gtk_button.


static void
gtk_button_class_init (GtkButtonClass *klass)
{
  GObjectClass *gobject_class;
  GtkObjectClass *object_class;
  GtkWidgetClass *widget_class;
  GtkContainerClass *container_class;

  gobject_class = G_OBJECT_CLASS (klass);
  object_class = (GtkObjectClass*) klass;
  widget_class = (GtkWidgetClass*) klass;
  container_class = (GtkContainerClass*) klass;

  gobject_class->constructor = gtk_button_constructor;
  gobject_class->set_property = gtk_button_set_property;
  gobject_class->get_property = gtk_button_get_property;

Dan di gtkobject.h Anda menemukan deklarasi berikut:


struct _GtkObjectClass
{
  GInitiallyUnownedClass parent_class;

  /* Non overridable class methods to set and get per class arguments */
  void (*set_arg) (GtkObject *object,
           GtkArg    *arg,
           guint      arg_id);
  void (*get_arg) (GtkObject *object,
           GtkArg    *arg,
           guint      arg_id);

  /* Default signal handler for the ::destroy signal, which is
   *  invoked to request that references to the widget be dropped.
   *  If an object class overrides destroy() in order to perform class
   *  specific destruction then it must still invoke its superclass'
   *  implementation of the method after it is finished with its
   *  own cleanup. (See gtk_widget_real_destroy() for an example of
   *  how to do this).
   */
  void (*destroy)  (GtkObject *object);
};

Hal-hal (* set_arg) adalah sebuah pointer untuk berfungsi dan ini dapat misalnya ditugaskan implementasi lain di beberapa kelas turunan.

Seringkali Anda melihat sesuatu seperti ini

struct function_table {
   char *name;
   void (*some_fun)(int arg1, double arg2);
};

void function1(int  arg1, double arg2)....


struct function_table my_table [] = {
    {"function1", function1},
...

Jadi Anda dapat menjangkau ke dalam tabel dengan nama dan memanggil fungsi "terkait".

Atau mungkin Anda menggunakan tabel hash di mana Anda meletakkan fungsi dan menyebutnya "dengan nama".

Salam
Friedrich

Friedrich
sumber
Apakah mungkin menggunakan function_table untuk fungsi hashing dalam implementasi tabel hash itu sendiri? (Baca: ketergantungan sirkular terlibat).
Flavius
2

Dapat menggunakannya dengan cara seperti ini:

//! Define:
#define F_NUM 3
int (*pFunctions[F_NUM])(void * arg);

//! Initialise:
int someFunction(void * arg) {
    int a= *((int*)arg);
    return a*a;
}

pFunctions[0]= someFunction;

//! Use:
int someMethod(int idx, void * arg, int * result) {
    int done= 0;
    if (idx < F_NUM && pFunctions[idx] != NULL) {
        *result= pFunctions[idx](arg);
        done= 1;
    }
    return done;
}

int x= 2;
int z= 0;
someMethod(0, (void*)&x, &z);
assert(z == 4);
Peter Hirt
sumber
1

Ini harus berupa contoh kode copy & paste singkat & sederhana dari tanggapan di atas. Semoga ini bisa membantu.

#include <iostream>
using namespace std;

#define DBG_PRINT(x) do { std::printf("Line:%-4d" "  %15s = %-10d\n", __LINE__, #x, x); } while(0);

void F0(){ printf("Print F%d\n", 0); }
void F1(){ printf("Print F%d\n", 1); }
void F2(){ printf("Print F%d\n", 2); }
void F3(){ printf("Print F%d\n", 3); }
void F4(){ printf("Print F%d\n", 4); }
void (*fArrVoid[N_FUNC])() = {F0, F1, F2, F3, F4};

int Sum(int a, int b){ return(a+b); }
int Sub(int a, int b){ return(a-b); }
int Mul(int a, int b){ return(a*b); }
int Div(int a, int b){ return(a/b); }
int (*fArrArgs[4])(int a, int b) = {Sum, Sub, Mul, Div};

int main(){
    for(int i = 0; i < 5; i++)  (*fArrVoid[i])();
    printf("\n");

    DBG_PRINT((*fArrArgs[0])(3,2))
    DBG_PRINT((*fArrArgs[1])(3,2))
    DBG_PRINT((*fArrArgs[2])(3,2))
    DBG_PRINT((*fArrArgs[3])(3,2))

    return(0);
}
nimig18
sumber
Jika itu adalah copy & paste dari jawaban lain, saya tidak yakin itu menambah nilai ...
Fabio mengatakan Reinstate Monica
Ya saya mengerti maksud Anda, saya akan menambahkan nilai malam ini di tempat kerja.
nimig18
1

Solusi paling sederhana adalah dengan memberikan alamat vektor akhir yang Anda inginkan, dan memodifikasinya di dalam fungsi.

void calculation(double result[] ){  //do the calculation on result

   result[0] = 10+5;
   result[1] = 10 +6;
   .....
}

int main(){

    double result[10] = {0}; //this is the vector of the results

    calculation(result);  //this will modify result
}
Leonardo
sumber
0

Pertanyaan ini sudah dijawab dengan contoh yang sangat bagus. Satu-satunya contoh yang mungkin hilang adalah di mana fungsi mengembalikan pointer. Saya menulis contoh lain dengan ini, dan menambahkan banyak komentar, kalau-kalau ada yang merasa terbantu:

#include <stdio.h>

char * func1(char *a) {
    *a = 'b';
    return a;
}

char * func2(char *a) {
    *a = 'c';
    return a;
}

int main() {
    char a = 'a';
    /* declare array of function pointers
     * the function pointer types are char * name(char *)
     * A pointer to this type of function would be just
     * put * before name, and parenthesis around *name:
     *   char * (*name)(char *)
     * An array of these pointers is the same with [x]
     */
    char * (*functions[2])(char *) = {func1, func2};
    printf("%c, ", a);
    /* the functions return a pointer, so I need to deference pointer
     * Thats why the * in front of the parenthesis (in case it confused you)
     */
    printf("%c, ", *(*functions[0])(&a)); 
    printf("%c\n", *(*functions[1])(&a));

    a = 'a';
    /* creating 'name' for a function pointer type
     * funcp is equivalent to type char *(*funcname)(char *)
     */
    typedef char *(*funcp)(char *);
    /* Now the declaration of the array of function pointers
     * becomes easier
     */
    funcp functions2[2] = {func1, func2};

    printf("%c, ", a);
    printf("%c, ", *(*functions2[0])(&a));
    printf("%c\n", *(*functions2[1])(&a));

    return 0;
}
Jay Medina
sumber
0

Contoh sederhana ini untuk array multidimensi dengan pointer fungsi ":

void one( int a, int b){    printf(" \n[ ONE ]  a =  %d   b = %d",a,b);}
void two( int a, int b){    printf(" \n[ TWO ]  a =  %d   b = %d",a,b);}
void three( int a, int b){    printf("\n [ THREE ]  a =  %d   b = %d",a,b);}
void four( int a, int b){    printf(" \n[ FOUR ]  a =  %d   b = %d",a,b);}
void five( int a, int b){    printf(" \n [ FIVE ]  a =  %d   b = %d",a,b);}
void(*p[2][2])(int,int)   ;
int main()
{
    int i,j;
    printf("multidimensional array with function pointers\n");

    p[0][0] = one;    p[0][1] = two;    p[1][0] = three;    p[1][1] = four;
    for (  i  = 1 ; i >=0; i--)
        for (  j  = 0 ; j <2; j++)
            (*p[i][j])( (i, i*j);
    return 0;
}
arun kumar
sumber