Pertanyaan Bagaimana fungsi pointer dalam kerja C?


Saya memiliki beberapa pengalaman akhir-akhir ini dengan fungsi pointer di C.

Jadi dengan tradisi menjawab pertanyaan Anda sendiri, saya memutuskan untuk membuat ringkasan kecil dari hal-hal yang sangat mendasar, bagi mereka yang membutuhkan penyelarasan cepat untuk subjek ini.


1006
2018-05-08 15:49


asal


Jawaban:


Fungsi pointer di C

Mari kita mulai dengan fungsi dasar seperti apa kita nantinya menunjuk ke:

int addInt(int n, int m) {
    return n+m;
}

Pertama, mari kita mendefinisikan pointer ke fungsi yang menerima 2 intdan mengembalikan sebuah int:

int (*functionPtr)(int,int);

Sekarang kita dapat mengarahkan ke fungsi kita:

functionPtr = &addInt;

Sekarang kita memiliki pointer ke fungsi, mari kita gunakan:

int sum = (*functionPtr)(2, 3); // sum == 5

Melewati pointer ke fungsi lain pada dasarnya sama:

int add2to3(int (*functionPtr)(int, int)) {
    return (*functionPtr)(2, 3);
}

Kita dapat menggunakan pointer fungsi dalam nilai-nilai kembali juga (coba untuk tetap up, itu menjadi berantakan):

// this is a function called functionFactory which receives parameter n
// and returns a pointer to another function which receives two ints
// and it returns another int
int (*functionFactory(int n))(int, int) {
    printf("Got parameter %d", n);
    int (*functionPtr)(int,int) = &addInt;
    return functionPtr;
}

Tapi itu jauh lebih baik menggunakan typedef:

typedef int (*myFuncDef)(int, int);
// note that the typedef name is indeed myFuncDef

myFuncDef functionFactory(int n) {
    printf("Got parameter %d", n);
    myFuncDef functionPtr = &addInt;
    return functionPtr;
}

1245
2018-05-08 15:49



Function pointer di C dapat digunakan untuk melakukan pemrograman berorientasi objek dalam C.

Misalnya, baris berikut ditulis dalam C:

String s1 = newString();
s1->set(s1, "hello");

Ya, itu -> dan kurangnya a new operator adalah pemberian mati, tetapi tampaknya menyiratkan bahwa kami sedang mengatur teks sebagian String kelas menjadi "hello".

Dengan menggunakan pointer fungsi, dimungkinkan untuk meniru metode dalam C.

Bagaimana ini bisa dilakukan?

Itu String kelas sebenarnya adalah a struct dengan sekelompok pointer fungsi yang bertindak sebagai cara untuk mensimulasikan metode. Berikut ini adalah deklarasi parsial dari String kelas:

typedef struct String_Struct* String;

struct String_Struct
{
    char* (*get)(const void* self);
    void (*set)(const void* self, char* value);
    int (*length)(const void* self);
};

char* getString(const void* self);
void setString(const void* self, char* value);
int lengthString(const void* self);

String newString();

Seperti dapat dilihat, metode dari String class sebenarnya berfungsi sebagai pointer ke fungsi yang dideklarasikan. Dalam mempersiapkan contoh dari String, yang newString fungsi dipanggil untuk mengatur fungsi pointer ke fungsi masing-masing:

String newString()
{
    String self = (String)malloc(sizeof(struct String_Struct));

    self->get = &getString;
    self->set = &setString;
    self->length = &lengthString;

    self->set(self, "");

    return self;
}

Misalnya, getString fungsi yang dipanggil dengan memanggil get metode didefinisikan sebagai berikut:

char* getString(const void* self_obj)
{
    return ((String)self_obj)->internal->value;
}

Satu hal yang dapat diperhatikan adalah bahwa tidak ada konsep instance dari suatu objek dan memiliki metode yang sebenarnya merupakan bagian dari objek, sehingga "objek diri" harus diteruskan pada setiap doa. (Dan itu internal hanya tersembunyi struct yang dihilangkan dari daftar kode sebelumnya - itu adalah cara melakukan penyembunyian informasi, tapi itu tidak relevan dengan fungsi pointer.)

Jadi, daripada bisa melakukannya s1->set("hello");, seseorang harus meneruskan objek untuk melakukan aksi s1->set(s1, "hello").

Dengan penjelasan kecil yang harus dilewatkan dalam referensi untuk diri sendiri, kita akan pindah ke bagian selanjutnya, yaitu warisan di C.

Katakanlah kita ingin membuat subkelas String, katakanlah ImmutableString. Agar string tidak berubah, maka set metode tidak akan dapat diakses, sambil mempertahankan akses ke get dan length, dan memaksa "konstruktor" untuk menerima char*:

typedef struct ImmutableString_Struct* ImmutableString;

struct ImmutableString_Struct
{
    String base;

    char* (*get)(const void* self);
    int (*length)(const void* self);
};

ImmutableString newImmutableString(const char* value);

Pada dasarnya, untuk semua subclass, metode yang tersedia sekali lagi berfungsi sebagai pointer. Kali ini, deklarasi untuk set metode tidak ada, oleh karena itu, tidak dapat dipanggil dalam ImmutableString.

Adapun implementasi dari ImmutableString, satu - satunya kode yang relevan adalah fungsi "konstruktor", yang newImmutableString:

ImmutableString newImmutableString(const char* value)
{
    ImmutableString self = (ImmutableString)malloc(sizeof(struct ImmutableString_Struct));

    self->base = newString();

    self->get = self->base->get;
    self->length = self->base->length;

    self->base->set(self->base, (char*)value);

    return self;
}

Dalam instantiating ImmutableString, fungsi menunjuk ke get dan length metode sebenarnya mengacu pada String.get dan String.length metode, dengan pergi melalui base variabel yang disimpan secara internal String obyek.

Penggunaan penunjuk fungsi dapat memperoleh pewarisan metode dari superclass.

Kami dapat terus melanjutkan polimorfisme di C.

Jika misalnya kita ingin mengubah perilaku length metode untuk kembali 0 sepanjang waktu di ImmutableString kelas untuk beberapa alasan, semua yang harus dilakukan adalah:

  1. Tambahkan fungsi yang akan berfungsi sebagai override length metode.
  2. Pergi ke "konstruktor" dan mengatur pointer fungsi ke override length metode.

Menambahkan override length metode dalam ImmutableString dapat dilakukan dengan menambahkan lengthOverrideMethod:

int lengthOverrideMethod(const void* self)
{
    return 0;
}

Kemudian, penunjuk fungsi untuk length metode di konstruktor terhubung ke lengthOverrideMethod:

ImmutableString newImmutableString(const char* value)
{
    ImmutableString self = (ImmutableString)malloc(sizeof(struct ImmutableString_Struct));

    self->base = newString();

    self->get = self->base->get;
    self->length = &lengthOverrideMethod;

    self->base->set(self->base, (char*)value);

    return self;
}

Sekarang, daripada memiliki perilaku yang identik untuk length metode dalam ImmutableString kelas sebagai String kelas, sekarang length metode akan mengacu pada perilaku yang didefinisikan dalam lengthOverrideMethod fungsi.

Saya harus menambahkan disclaimer bahwa saya masih belajar bagaimana menulis dengan gaya pemrograman berorientasi objek di C, jadi mungkin ada poin yang tidak saya jelaskan dengan baik, atau mungkin hanya meleset dari segi cara terbaik untuk mengimplementasikan OOP di C. Tapi tujuan saya adalah untuk mencoba menggambarkan salah satu dari banyak penggunaan fungsi pointer.

Untuk informasi lebih lanjut tentang cara melakukan pemrograman berorientasi objek di C, silakan merujuk ke pertanyaan berikut:


267



Panduan untuk dipecat: Cara menyalahgunakan fungsi pointer di GCC pada mesin x86 dengan mengkompilasi kode Anda dengan tangan:

  1. Mengembalikan nilai saat ini pada daftar EAX

    int eax = ((int(*)())("\xc3 <- This returns the value of the EAX register"))();
    
  2. Tulis fungsi swap

    int a = 10, b = 20;
    ((void(*)(int*,int*))"\x8b\x44\x24\x04\x8b\x5c\x24\x08\x8b\x00\x8b\x1b\x31\xc3\x31\xd8\x31\xc3\x8b\x4c\x24\x04\x89\x01\x8b\x4c\x24\x08\x89\x19\xc3 <- This swaps the values of a and b")(&a,&b);
    
  3. Tulis penghitung for-loop ke 1000, panggil beberapa fungsi setiap kali

    ((int(*)())"\x66\x31\xc0\x8b\x5c\x24\x04\x66\x40\x50\xff\xd3\x58\x66\x3d\xe8\x03\x75\xf4\xc3")(&function); // calls function with 1->1000
    
  4. Anda bahkan dapat menulis fungsi rekursif yang jumlahnya mencapai 100

    const char* lol = "\x8b\x5c\x24\x4\x3d\xe8\x3\x0\x0\x7e\x2\x31\xc0\x83\xf8\x64\x7d\x6\x40\x53\xff\xd3\x5b\xc3\xc3 <- Recursively calls the function at address lol.";
    i = ((int(*)())(lol))(lol);
    

187



Salah satu kegunaan favorit saya untuk fungsi pointer adalah iterator murah dan mudah -

#include <stdio.h>
#define MAX_COLORS  256

typedef struct {
    char* name;
    int red;
    int green;
    int blue;
} Color;

Color Colors[MAX_COLORS];


void eachColor (void (*fp)(Color *c)) {
    int i;
    for (i=0; i<MAX_COLORS; i++)
        (*fp)(&Colors[i]);
}

void printColor(Color* c) {
    if (c->name)
        printf("%s = %i,%i,%i\n", c->name, c->red, c->green, c->blue);
}

int main() {
    Colors[0].name="red";
    Colors[0].red=255;
    Colors[1].name="blue";
    Colors[1].blue=255;
    Colors[2].name="black";

    eachColor(printColor);
}

95



Fungsi pointer menjadi mudah untuk menyatakan setelah Anda memiliki deklarator dasar:

  • id: ID: ID adalah a
  • Penunjuk: *D: D pointer ke
  • Fungsi: D(<parameters>): D fungsi mengambil <parameter> kembali

Sementara D adalah deklarator lain yang dibangun menggunakan aturan yang sama. Pada akhirnya, di suatu tempat, itu berakhir dengan ID (lihat di bawah untuk contoh), yang merupakan nama entitas yang dideklarasikan. Mari kita coba untuk membangun fungsi yang mengambil penunjuk ke fungsi yang tidak mengambil apa pun dan mengembalikan int, dan mengembalikan pointer ke fungsi yang mengambil int dan mengembalikan int. Dengan tipe-defs seperti ini

typedef int ReturnFunction(char);
typedef int ParameterFunction(void);
ReturnFunction *f(ParameterFunction *p);

Seperti yang Anda lihat, itu cukup mudah untuk membangunnya menggunakan typedefs. Tanpa typedef, itu tidak sulit baik dengan aturan deklarator di atas, diterapkan secara konsisten. Seperti yang Anda lihat saya melewatkan bagian yang menunjuk pointer, dan hal yang dikembalikan fungsi. Itulah yang muncul di bagian paling kiri deklarasi, dan tidak menarik: Ini ditambahkan di bagian akhir jika ada yang membangun deklarator. Ayo lakukan itu. Membangunnya secara konsisten, pertama bertele-tele - menunjukkan struktur menggunakan [ dan ]:

function taking 
    [pointer to [function taking [void] returning [int]]] 
returning
    [pointer to [function taking [char] returning [int]]]

Seperti yang Anda lihat, seseorang dapat mendeskripsikan suatu tipe sepenuhnya dengan menambahkan deklarator satu demi satu. Konstruksi dapat dilakukan dengan dua cara. Salah satunya adalah bottom-up, dimulai dengan hal yang sangat benar (daun) dan bekerja jalan sampai ke identifier. Cara lain adalah top-down, dimulai dari identifier, bekerja hingga ke daun. Saya akan menunjukkan dua cara.

Bottom Up

Konstruksi dimulai dengan hal di sebelah kanan: Benda itu kembali, yang merupakan fungsi mengambil arang. Agar deklarator tetap berbeda, saya akan memberi nomor:

D1(char);

Dimasukkan parameter char secara langsung, karena itu sepele. Menambahkan pointer ke deklarator dengan mengganti D1 oleh *D2. Perhatikan bahwa kita harus membungkus tanda kurung *D2. Itu bisa diketahui dengan mencari prioritas dari *-operator dan operator panggilan-fungsi (). Tanpa tanda kurung kami, kompiler akan membacanya sebagai *(D2(char p)). Tapi itu tidak akan menjadi pengganti biasa dari D1 oleh *D2 lagi, tentu saja. Tanda kurung selalu diizinkan di sekitar deklarator. Jadi Anda tidak membuat kesalahan jika Anda menambahkan terlalu banyak dari mereka, sebenarnya.

(*D2)(char);

Jenis pengembalian selesai! Sekarang, mari ganti D2 oleh deklarator fungsi fungsi pengambilan <parameters> kembali, yang mana D3(<parameters>) yang mana kita sekarang.

(*D3(<parameters>))(char)

Perhatikan bahwa tidak perlu ada tanda kurung, karena kami ingin  D3 menjadi deklarator fungsi dan bukan deklarator pointer saat ini. Hebat, hanya yang tersisa adalah parameter untuk itu. Parameter dilakukan persis sama dengan yang kami lakukan pada tipe kembalian, hanya dengan char digantikan oleh void. Jadi saya akan menyalinnya:

(*D3(   (*ID1)(void)))(char)

Saya telah diganti D2 oleh ID1, karena kita sudah selesai dengan parameter itu (itu sudah pointer ke fungsi - tidak perlu deklarator lain). ID1 akan menjadi nama parameter. Sekarang, saya katakan di atas pada akhirnya, tambahkan jenis yang semua declarator modifikasi - yang muncul di bagian paling kiri dari setiap deklarasi. Untuk fungsi, yang menjadi tipe kembalinya. Untuk pointer yang menunjuk untuk mengetik dll ... Ini menarik ketika dituliskan jenisnya, itu akan muncul dalam urutan yang berlawanan, di sebelah kanan :) Lagi pula, menggantikannya menghasilkan deklarasi lengkap. Kedua waktu int tentu saja.

int (*ID0(int (*ID1)(void)))(char)

Saya sudah menyebut identifier dari fungsi ID0 dalam contoh itu.

Top Down

Ini dimulai pada identifier di bagian paling kiri dalam deskripsi tipe, membungkus deklarator itu ketika kita berjalan di sebelah kanan. Dimulai dari fungsi pengambilan <parameter> kembali

ID0(<parameters>)

Hal berikutnya dalam deskripsi (setelah "kembali") adalah arahkan ke. Mari gabungkan itu:

*ID0(<parameters>)

Lalu hal selanjutnya adalah functon taking <parameter> kembali. Parameternya adalah arang sederhana, jadi kita langsung memasukkannya lagi, karena itu benar-benar sepele.

(*ID0(<parameters>))(char)

Perhatikan tanda kurung kami tambahkan, karena kami ingin lagi bahwa * mengikat pertama, dan kemudian itu (char). Kalau tidak, itu akan membaca fungsi pengambilan <parameter> mengembalikan fungsi .... Noes, fungsi pengembalian fungsi bahkan tidak diizinkan.

Sekarang kita hanya perlu menempatkan <parameter>. Saya akan menunjukkan versi singkat dari deriveration, karena saya pikir Anda sudah sekarang memiliki ide bagaimana melakukannya.

pointer to: *ID1
... function taking void returning: (*ID1)(void)

Taruh saja int sebelum para declarator seperti yang kami lakukan dengan bottom-up, dan kami selesai

int (*ID0(int (*ID1)(void)))(char)

Hal yang menyenangkan

Apakah bottom-up atau top-down lebih baik? Saya terbiasa dengan bottom-up, tetapi beberapa orang mungkin lebih nyaman dengan top-down. Ini masalah selera yang saya pikir. Kebetulan, jika Anda menerapkan semua operator dalam deklarasi itu, Anda akan mendapatkan int:

int v = (*ID0(some_function_pointer))(some_char);

Itu adalah properti deklarasi yang bagus di C: Deklarasi tersebut menegaskan bahwa jika operator tersebut digunakan dalam ekspresi menggunakan identifier, maka ia akan menghasilkan jenis di sebelah kiri. Ini seperti itu untuk array juga.

Semoga Anda menyukai tutorial kecil ini! Sekarang kita dapat menautkan ke ini ketika orang bertanya-tanya tentang sintaks fungsi pernyataan yang aneh. Saya mencoba menempatkan internal C sesedikit mungkin. Jangan sungkan untuk mengedit / memperbaiki hal-hal di dalamnya.


23



Penggunaan bagus lainnya untuk pointer fungsi:
Beralih antar versi tanpa rasa sakit

Mereka sangat berguna untuk digunakan ketika Anda ingin fungsi yang berbeda pada waktu yang berbeda, atau fase pembangunan yang berbeda. Sebagai contoh, saya mengembangkan aplikasi pada komputer host yang memiliki konsol, tetapi rilis final dari perangkat lunak akan diletakkan pada Avnet ZedBoard (yang memiliki port untuk display dan konsol, tetapi mereka tidak diperlukan / diinginkan untuk rilisan final). Jadi selama pengembangan, saya akan menggunakannya printf untuk melihat status dan pesan kesalahan, tetapi setelah selesai, saya tidak ingin mencetak apa pun. Inilah yang telah saya lakukan:

version.h

// First, undefine all macros associated with version.h
#undef DEBUG_VERSION
#undef RELEASE_VERSION
#undef INVALID_VERSION


// Define which version we want to use
#define DEBUG_VERSION       // The current version
// #define RELEASE_VERSION  // To be uncommented when finished debugging

#ifndef __VERSION_H_      /* prevent circular inclusions */
    #define __VERSION_H_  /* by using protection macros */
    void board_init();
    void noprintf(const char *c, ...); // mimic the printf prototype
#endif

// Mimics the printf function prototype. This is what I'll actually 
// use to print stuff to the screen
void (* zprintf)(const char*, ...); 

// If debug version, use printf
#ifdef DEBUG_VERSION
    #include <stdio.h>
#endif

// If both debug and release version, error
#ifdef DEBUG_VERSION
#ifdef RELEASE_VERSION
    #define INVALID_VERSION
#endif
#endif

// If neither debug or release version, error
#ifndef DEBUG_VERSION
#ifndef RELEASE_VERSION
    #define INVALID_VERSION
#endif
#endif

#ifdef INVALID_VERSION
    // Won't allow compilation without a valid version define
    #error "Invalid version definition"
#endif

Di version.c Saya akan mendefinisikan 2 fungsi prototipe yang ada version.h

version.c

#include "version.h"

/*****************************************************************************/
/**
* @name board_init
*
* Sets up the application based on the version type defined in version.h.
* Includes allowing or prohibiting printing to STDOUT.
*
* MUST BE CALLED FIRST THING IN MAIN
*
* @return    None
*
*****************************************************************************/
void board_init()
{
    // Assign the print function to the correct function pointer
    #ifdef DEBUG_VERSION
        zprintf = &printf;
    #else
        // Defined below this function
        zprintf = &noprintf;
    #endif
}

/*****************************************************************************/
/**
* @name noprintf
*
* simply returns with no actions performed
*
* @return   None
*
*****************************************************************************/
void noprintf(const char* c, ...)
{
    return;
}

Perhatikan bagaimana pointer fungsi di-prototipe version.h sebagai

void (* zprintf)(const char *, ...);

Ketika itu direferensikan dalam aplikasi, ia akan mulai mengeksekusi ke mana pun ia menunjuk, yang belum ditentukan.

Di version.c, perhatikan di board_init()berfungsi dimana zprintf ditugaskan fungsi yang unik (yang cocok tanda tangan fungsi) tergantung pada versi yang didefinisikan dalam version.h

zprintf = &printf zprintf memanggil printf untuk keperluan debugging

atau

zprintf = &noprint zprintf hanya mengembalikan dan tidak akan menjalankan kode yang tidak perlu

Menjalankan kode akan terlihat seperti ini:

mainProg.c

#include "version.h"
#include <stdlib.h>
int main()
{
    // Must run board_init(), which assigns the function
    // pointer to an actual function
    board_init();

    void *ptr = malloc(100); // Allocate 100 bytes of memory
    // malloc returns NULL if unable to allocate the memory.

    if (ptr == NULL)
    {
        zprintf("Unable to allocate memory\n");
        return 1;
    }

    // Other things to do...
    return 0;
}

Kode di atas akan digunakan printf jika dalam mode debug, atau tidak melakukan apa pun jika dalam mode rilis. Ini jauh lebih mudah daripada menelusuri keseluruhan proyek dan mengomentari atau menghapus kode. Yang perlu saya lakukan hanyalah mengubah versinya version.h dan kode akan melakukan sisanya!


21



Function pointer biasanya didefinisikan oleh typedef, dan digunakan sebagai param & return value,

Jawaban di atas sudah menjelaskan banyak, saya hanya memberikan contoh lengkap:

#include <stdio.h>

#define NUM_A 1
#define NUM_B 2

// define a function pointer type
typedef int (*two_num_operation)(int, int);

// an actual standalone function
static int sum(int a, int b) {
    return a + b;
}

// use function pointer as param,
static int sum_via_pointer(int a, int b, two_num_operation funp) {
    return (*funp)(a, b);
}

// use function pointer as return value,
static two_num_operation get_sum_fun() {
    return &sum;
}

// test - use function pointer as variable,
void test_pointer_as_variable() {
    // create a pointer to function,
    two_num_operation sum_p = &sum;
    // call function via pointer
    printf("pointer as variable:\t %d + %d = %d\n", NUM_A, NUM_B, (*sum_p)(NUM_A, NUM_B));
}

// test - use function pointer as param,
void test_pointer_as_param() {
    printf("pointer as param:\t %d + %d = %d\n", NUM_A, NUM_B, sum_via_pointer(NUM_A, NUM_B, &sum));
}

// test - use function pointer as return value,
void test_pointer_as_return_value() {
    printf("pointer as return value:\t %d + %d = %d\n", NUM_A, NUM_B, (*get_sum_fun())(NUM_A, NUM_B));
}

int main() {
    test_pointer_as_variable();
    test_pointer_as_param();
    test_pointer_as_return_value();

    return 0;
}

13



Salah satu kegunaan besar untuk fungsi pointer di C adalah memanggil fungsi yang dipilih pada saat run-time. Sebagai contoh, pustaka C run-time memiliki dua rutinitas, qsort dan bsearch, yang mengambil penunjuk ke fungsi yang dipanggil untuk membandingkan dua item yang disortir; ini memungkinkan Anda untuk mengurutkan atau mencari, masing-masing, apa pun, berdasarkan kriteria apa pun yang ingin Anda gunakan.

Contoh yang sangat mendasar, jika ada satu fungsi yang disebut print (int x, int y) yang pada gilirannya mungkin perlu memanggil fungsi add () atau sub () yang memiliki tipe yang sama maka apa yang akan kita lakukan, kita akan menambahkan satu fungsi argumen penunjuk ke fungsi cetak () seperti ditunjukkan di bawah ini: -

int add()
{
   return (100+10);
}

int sub()
{
   return (100-10);
}

void print(int x, int y, int (*func)())
{
    printf("value is : %d", (x+y+(*func)()));
}

int main()
{
    int x=100, y=200;
    print(x,y,add);
    print(x,y,sub);

    return 0;
}

7



Mulai dari fungsi gores memiliki Beberapa Alamat Memori Dari Mana Mereka mulai mengeksekusi. Dalam Bahasa Assembly Mereka disebut sebagai (memanggil "alamat memori fungsi"). Sekarang kembali ke C Jika fungsi memiliki alamat memori maka mereka dapat dimanipulasi oleh Pointer di C.Jadi Dengan aturan C

1. Pertama, Anda perlu mendeklarasikan pointer ke fungsi 2. Lulus Alamat dari fungsi yang Diinginkan

**** Catatan-> fungsi harus dari tipe yang sama ****

Program Sederhana ini akan Menggambarkan Setiap Hal.

#include<stdio.h>
void (*print)() ;//Declare a  Function Pointers
void sayhello();//Declare The Function Whose Address is to be passed
                //The Functions should Be of Same Type
int main()
{

 print=sayhello;//Addressof sayhello is assigned to print
 print();//print Does A call To The Function 
 return 0;
}

void sayhello()
{
 printf("\n Hello World");
}

enter image description hereSetelah Itu, mari kita Lihat Bagaimana mesin Memahami Mereka. Gipulir instruksi mesin dari program di atas dalam arsitektur 32 bit.

Area tanda merah menunjukkan bagaimana alamat ditukar dan disimpan di eax. Kemudian mereka adalah instruksi panggilan pada eax. eax berisi alamat yang diinginkan dari fungsi tersebut


3



Karena fungsi pointer sering diketik callback, Anda mungkin ingin melihat ketik callback yang aman. Hal yang sama berlaku untuk titik masuk, dll fungsi yang bukan callback.

C cukup berubah-ubah dan memaafkan pada saat yang sama :)


0



pointer fungsi berguna dalam banyak situasi, misalnya:

  • Anggota objek COM adalah pointer ke fungsi ag: This->lpVtbl->AddRef(This); AddRef adalah penunjuk ke fungsi.
  • fungsi panggilan balik, misalnya fungsi yang ditentukan pengguna untuk membandingkan dua variabel dilewatkan sebagai panggilan balik ke fungsi pengurutan khusus.
  • sangat berguna untuk implementasi plugin dan SDK aplikasi.

-8