Hướng dẫn lập trình C Linux Phần 25 - Con trỏ hàm

theanh

Administrator
Nhân viên
Cho đến nay trong loạt bài hướng dẫn lập trình C đang diễn ra này, chúng ta đã thảo luận về khái niệm cơ bản về con trỏ cũng như một số khía cạnh liên quan đến con trỏ, như con trỏ đến một mảng và mảng con trỏ. Mở rộng hiểu biết của chúng ta về con trỏ, trong hướng dẫn này, chúng ta sẽ thảo luận về khái niệm con trỏ đến hàm.

Con trỏ hàm trong ngôn ngữ lập trình C​

Cũng giống như chúng ta có con trỏ đến biến, cũng có thể có con trỏ đến hàm. Sau đây là một ví dụ về khai báo con trỏ hàm:
Mã:
void (*fn_ptr)(int)
Vì vậy, ở đây chúng ta có một con trỏ hàm có tên 'fn_ptr' có thể trỏ đến bất kỳ hàm nào trả về void và chấp nhận một số nguyên làm đầu vào. Không cần phải nói, đây chỉ là phần khai báo - giống như bất kỳ con trỏ nào khác, bạn cần gán cho nó một địa chỉ (trong trường hợp này là địa chỉ của một hàm) để sử dụng nó.

Sau đây là một ví dụ sử dụng con trỏ này:
Mã:
#include 

void print_int(int a)
{
 printf("\n Giá trị số nguyên là: %d\n",a);
}

int main()
{
 void (*fn_ptr)(int);
 fn_ptr = &print_int;
 (*fn_ptr)(10);

 return 0;
}
Như bạn thấy, trước tiên chúng ta định nghĩa một hàm 'print_int' chấp nhận một số nguyên và trả về void. Sau đó, trong hàm 'main', chúng ta khai báo 'fn_ptr' là một con trỏ hàm có thể trỏ đến các hàm như 'print_int'. Tiếp theo là gán địa chỉ của hàm 'print_int' cho 'fn_ptr' và cuối cùng, thực hiện lệnh gọi hàm bằng con trỏ.

Đây là kết quả đầu ra:
Mã:
Theintegervalueis:10
Điều đáng nói ở đây là bạn có thể đơn giản hóa chương trình này hơn nữa bằng cách tránh & và * khỏi hai dòng cuối cùng. Sau đây là mã đã sửa đổi:
Mã:
#include 

void print_int(int a)
{
 printf("\n Giá trị số nguyên là: %d\n",a);
}

int main()
{
 void (*fn_ptr)(int);
 fn_ptr = print_int;
 fn_ptr(10);

 return 0;
}
Tiếp tục, giống như một mảng các con trỏ, bạn cũng có thể có một mảng các con trỏ hàm. Ví dụ, sau đây là một mảng các con trỏ hàm có khả năng lưu trữ 3 địa chỉ hàm.
Mã:
void (*fn_ptr[3])(int)
Sau đây là một ví dụ sử dụng mảng các con trỏ này:
Mã:
void print_int1(int a)
{
 printf("\n Giá trị số nguyên là: %d\n",a);
}

void print_int2(int a)
{
 printf("\n Giá trị số nguyên là: %d\n",a+1);
}

void print_int3(int a)
{
 printf("\n Giá trị số nguyên là: %d\n",a+2);
}

int main()
{
 void (*fn_ptr[3])(int);
 
 fn_ptr[0] = print_int1;
 fn_ptr[1] = print_int2;
 fn_ptr[2] = print_int3;
 
 fn_ptr[0](10);
 fn_ptr[1](10);
 fn_ptr[2](10);

 return 0;
}
Đây là đầu ra được tạo ra bởi đoạn mã này:
Mã:
Giá trị số nguyên là: 10 
 
Giá trị số nguyên là: 11 
 
Giá trị số nguyên là: 12
Một khía cạnh khác của con trỏ hàm mà bạn nên biết là bạn cũng có thể sử dụng chúng làm đối số hàm. Ví dụ, có thể có một hàm chấp nhận một con trỏ đến một hàm làm đối số. Ví dụ:
Mã:
void some_random_func(void (*fn_ptr)(int))
Sau đây là một ví dụ về mã sử dụng hàm này:
Mã:
#include 

void another_random_func(int a)
{
 printf("\n Số nguyên cần nhập là: %d\n", a);
}

void some_random_func(void (*fn_ptr)(int))
{
 fn_ptr(5);
}


int main()
{
 some_random_func(another_random_func);
 return 0;
}
Vì vậy, những gì chúng ta đã làm ở đây là tạo một hàm có tên là 'some_random_func' chấp nhận một con trỏ hàm trong đầu vào. Sau đó, từ 'main', chúng ta gọi 'some_random_func' với địa chỉ của một hàm khác 'another_random_func' làm đối số. Sau đó, sử dụng con trỏ, chúng ta đã gọi thành công 'another_random_func'.

Đây là đầu ra:
Mã:
Theintegertoenteredis:5

Kết luận​

Con trỏ hàm có thể hữu ích khi bạn muốn tạo ra thứ gì đó gọi là 'cơ chế gọi lại' (đọc thêm về nó tại đây). Nhưng trước khi đi sâu vào vấn đề đó, tốt hơn hết là bạn nên hiểu rõ về khái niệm này. Chúng tôi khuyên bạn nên thử các ví dụ từ hướng dẫn này trên máy cục bộ của mình (và cũng tạo các ví dụ mới). Trong trường hợp có bất kỳ nghi ngờ hoặc thắc mắc nào, hãy để lại bình luận bên dưới.
 
Back
Bên trên