Cadvance · lập trình

Con trỏ hàm trong C

Lưu ý: nội dung bài viết chỉ áp dụng đối với ngôn ngữ lập trình C(not C++ vì mình chưa học)

1.Giới thiệu:

Trong C,Con trỏ hàm là một biến lưu trữ địa chỉ của một hàm, thông qua biến đó, ta có thể gọi hàm mà nó trỏ tới.

con trỏ hàm được khai báo như sau

<kiểu trả về> (*<tên con trỏ>)(<danh sách đối số>);

ví dụ:


int f1(int x);

/* prototype */ /* pointer to a fn with an int arg and int return */

int (*func)(int);

func = f1;

n = (*func)(5); /* same as f1(5)

Vì là 1 biến nên chúng ta hoàn toàn có thể tạo ra mảng các biên:


int (*bagOfTricks[10])(int, char *);

2. Ứng dụng:

1. Truyền vào hàm:

Ví dụ về một hàm cực kì phổ biến : qsort() của thư viện stdio.h

void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *));

int(*compar)(const void *, const void *) là con trỏ hàm đại diện cho hàm so sánh 2 phần tử mà kiểu trả về là int.


#include&lt;stdio.h&gt;

#include&lt;stdlib.h&gt;

/* qsort needs a compare function that returns 0 if x '==' y &lt;0 if x '&lt;' y &gt;0 if x '&gt;' y */

int compareInt(const void *x, const void *y) { return ((*(int *)x) - (*(int *)y)); }

struct student {

int id;

char *name;

char *address; };

int compareId(const void *x, const void *y) {

int key1, key2;

key1 = ((struct student *)x)-&gt;id;

key2 = ((struct student *)y)-&gt;id;

return (key1 - key2); }

int main(int argc, char **argv)
{
int i, n;
int *array;
char *strings;
if (argc != 2) {
fprintf(stderr, &quot;Usage: %s &lt;n&gt;\n&quot;, argv[0]) ;
exit(1);
}
n = atoi(argv[1]);
array = (int *) malloc(sizeof(int)*n);
srandom(0);
for (i=0; i&lt;n; i++) {
array[i] = random() % n;
}
qsort(array, n, sizeof(int), compareInt);
roster = (struct student *) malloc(sizeof(struct student)*n);
for (i=0; i&lt;n; i++) {
roster[i].id = n-i;
roster[i].name = NULL;
roster[i].address = NULL;
}
qsort(roster, n, sizeof(struct student), compareId);
exit(0);
}

2.Như một phần tử của struct:

#ifndef ADDRESS_H

#define ADDRESS_H

#include&lt;stdio.h&gt;

#include&lt;stdlib.h&gt;

#include&lt;time.h&gt;

typedef struct address address;

typedef struct address * Address;

struct address {

     char *name;

     char *streetAddress;

     char *city; char *state;

      int zip;
       char * (*toString)(Address); };

Address createAddress(char *, char *, char *, char *, int);

char *toString(Address);

char *printAddress(Address)

static int getLength(Address this) {

       return strlen(this-&gt;name)+strlen(this-&gt;streetAddress)+ strlen(this-&gt;city)+strlen(this-&gt;state)+4+5+10; }

Address createAddress(char *name, char *streetAddress, char *city, char *state, int zip) {

       Address temp = (Address) malloc(sizeof(address));

       temp-&gt;name = (char *) malloc(sizeof(char)*(strlen(name)+1));

       temp-&gt;streetAddress = (char *) malloc(sizeof(char (strlen(streetAddress)+1));
 
        temp-&gt;city = (char *) malloc(sizeof(char)*(strlen(city)+1));
 
        temp-&gt;state = (char *) malloc(sizeof(char)*(strlen(state)+1));

        strcpy(temp-&gt;name, name); strcpy(temp-&gt;streetAddress, streetAddress);

         strcpy(temp-&gt;city, city); strcpy(temp-&gt;state, state);

        temp-&gt;zip = zip; temp-&gt;toString = toString; return temp;

}

char *toString(Address this) {

       int len = getLength(this);

       char * temp = (char *) malloc(sizeof(char)*len);

        snprintf(temp, len, &quot;%s\n%s\n%s, %s, %d\n&quot;, this-&gt;name, this-&gt;streetAddress, this-&gt;city, this-&gt;state, this-&gt;zip);

       return temp;

}

char *printAddress(Address this) {

       int len = getLength(this);

       char * temp = (char *) malloc(sizeof(char)*len);

       snprintf(temp, len, &quot;%s, %s, %s, %s %d\n&quot;, this-&gt;name, this-&gt;streetAddress, this-&gt;city, this-&gt;state, this-&gt;zip); 
       return temp;

}

int main(int argc, char *argv[]) {

       Address addr1 = createAddress(&quot;Moo Shoo&quot;, &quot;123 Main Street&quot;, &quot;Boise&quot;, &quot;Idaho&quot;, 83701);

        printf(&quot;%s\n&quot;, (*addr1-&gt;toString)(addr1));

        addr1-&gt;toString = printAddress;

        printf(&quot;%s\n&quot;, (*addr1-&gt;toString)(addr1));

        exit(0);

}

3. Sử dụng một mảng những con trỏ hàm:

#include&lt;stdio.h&gt;

#include&lt;stdlib.h&gt;

int foobar0(int x) {

     printf(&quot;I have been invoked!!!! x=%d\n&quot;,x);

     return x;

}

int foobar1(int x) { printf(&quot;I have been invoked!!!! x=%d\n&quot;,x*2); return x; } int foobar2(int x) { printf(&quot;I have been invoked!!!! x=%d\n&quot;,x*3); return x; } void fun(int (*fn)(int x)) { int result; result = (*fn) (5); }
int main(int argc, char **argv)
{
    int i;
    int count=0;
    int (*names[3])(int);
    names[0] = foobar0;
    names[1] = foobar1;
    names[2] = foobar2;
    if (argc != 2) {
       fprintf(stderr,&quot;Usage %s: &lt;count&gt;\n&quot;,argv[0]);
       exit(1);
    }
   count = atoi(argv[1]);
   for (i=0; i&lt;count; i++) {
       fun(names[random()%3]);
   }
   exit(0);
}

 

 

Bình luận về bài viết này