PDA

View Full Version : Con trỏ tới hàm trong lập trình C?



stephen
10-10-2006, 07:58 PM
float Lonnhat(float (*f)(),float (*g)(),float x)
{
return ((*f)(x)>(*g)(x)?(*f)(x):(*g)(x));
}
float Binhphuong(float x)
{
return(x*x);
}
float Lapphuong(float x)
{
return(x*x*x);
}

void main()
{
float Lonnhat(),Binhphuong(),Lapphuong;
printf("\nNhap gia tri x=");
scanf("%f",&x);
printf("\nBinh phuong cua x=%f\tla%f",x,Binhphuong(x));
printf("\nLap phuong cua x=%f\tla%f",x,Linhphuong(x));
printf("\nSo lon nhat{x*x,x*x*x}=%f",Lonnhat(Binhphuong,lapphuong,x));
}

Bài này nó lại báo lỗi ko chạy, chỉ dùm em nha mấy huynh

nguyentuan2
11-10-2006, 09:27 AM
tui không rõ không chạy là như thế nào: lỗi hay chạy sai hay cái gì khác nữa

tui thì tui nghĩ bài này lỗi compile
ở chỗ này

1. float Lonnhat(float (*f)(),float (*g)(),float x)
->f, g là 2 hàm nhận kiểu void, trả ra kiểu float
2. trong main() bạn có lời gọi
printf("\nSo lon nhat{x*x,x*x*x}=%f",Lonnhat(Binhphuong,lapphuong,x ));
trong khi đó binhphuong và laptruong nhận input là 1 đối số kiểu float
->lỗi do khác prototype
theo như ý (1) nếu binhphuong và lập phương là 2 hàm không có đối số thì ko bị lỗi

bạn có thể sửa như sau


origin:
float Lonnhat(float (*f)(),float (*g)(),float x)
change to:
float Lonnhat(float (*f)(float),float (*g)(float),float x)

PoPoPoPo
11-10-2006, 01:52 PM
Trong C, khó nhất là về con trỏ, do đó phải hết sức cẩn thận khi làm viẹc với con trỏ, không khéo toàn bộ nhớ của bạn bị full đấy.

Tarzan
11-10-2006, 02:04 PM
Theo tôi để cho dễ dàng và sáng sủa -> đỡ bị lỗi linh tinh, tác giả bài này nên định nghĩa 1 kiểu dữ liệu mới như sau:

typedef float (* LPFN_FUNCVALUE)(float);

Như vậy sẽ không dẫn đến những việc nhầm lẫn vớ vẩn nữa. Chứ nhìn đoạn code trên thì ...

ndn
17-10-2006, 01:59 PM
Sửa lại theo bài của Bạn:

#include <stdio.h>
#include <conio.h>

float Lonnhat(float (*)(float), float (*)(float), float);
float Binhphuong(float);
float Lapphuong(float);
/**/

void main(){
/**/
float x;
printf("\nNhap gia tri x=");
scanf("%f",&x);

printf("\nBinh phuong cua x=%f\tla %f ",x,Binhphuong(x));
printf("\nLap phuong cua x=%f\tla %f \r\n",x,Lapphuong(x));
printf("\nSo lon nhat{x*x,x*x*x}=%f\r\n",Lonnhat(Binhphuong, Lapphuong,x ));
}

float Lonnhat(float (*f)(float),float (*g)(float),float x){

return ((*f)(x)>(*g)(x)?(*f)(x):(*g)(x));
}
/**/
float Binhphuong(float x){
return(x*x);
}
/**/
float Lapphuong(float x){
return(x*x*x);
}

hoặc có thể làm đơn giản hơn mà không dùng con trỏ hàm:
#include <stdio.h>
#include <conio.h>

float Lonnhat(float , float);
float Binhphuong(float);
float Lapphuong(float);
/**/

void main(){
/**/
float x;
printf("\nNhap gia tri x=");
scanf("%f",&x);

printf("\nBinh phuong cua x=%f\tla %f ",x,Binhphuong(x));
printf("\nLap phuong cua x=%f\tla %f \r\n",x,Lapphuong(x));
printf("\nSo lon nhat{x*x,x*x*x}=%f",Lonnhat(Binhphuong(x), Lapphuong(x)));
}
/**/
float Binhphuong(float x){
return(x*x);
}
/**/
float Lapphuong(float x){
return(x*x*x);
}
/**/
float Lonnhat(float a, float b){

return (a>=b)?a:b;
}

ndn
17-10-2006, 02:27 PM
Qua đây mình cũng muốn chia sẻ cho các bạn về cách sử dụng con trỏ hàm:
(trong sách nhập môn lập trình ngôn ngữ C- của thầy Nguyễn Thanh Thủy):
1. Khái niệm:
Mặc dù một hàm không phải là một biến nhưng nó vẫn chiếm vị trí trong bộ nhớ và ta có thể gán vào vị trí của nó cho một loại biến con trỏ. Con trỏ này trỏ đến điểm xâm nhập vào hàm. Ta gọi đây là con trỏ hàm. Con trỏ hàm có thể sử dụng thay cho tên hàm và việc sử dụng con trỏ cho phép các hàm cũng được truyền như là tham số cho các hàm khác.
Để hiểu được các con trỏ hàm làm việc như thế nào, ta cần hiểu một chút về cách biên dịch và gọi một hàm. Khi biên dịch hàm, trình biên dịch chuyển chương trình nguồn sang dạng mã máy và thiết lập một điểm xâm nhập vào hàm (chính là vị trí chỉ thị mã máy đầu tiên của hàm). Khi có lời gọi thực hiện hàm, máy tính sẽ thực hiện một chỉ thị call chuyển điều khiển đến điểm xâm nhập này. Trong trường hợp gọi hàm bằng tên hàm thì điểm xâm nhập này là trị tức thời (gần như là một hằng và không chứa biến nào cả), cách gọi hàm này gọi là cách gọi hàm trực tiếp. Trái lại, khi gọi hàm gián tiếp thông qua một biến trỏ thì biến trỏ đó phải trỏ tới chỉ thị mã máy đầu tiên của hàm đó. Cách gọi hàm thông qua biến trỏ hàm gọi là cách gọi hàm gián tiếp.

2. Khai báo biến con trỏ hàm
[kiểu giá trị](*tên biến trỏ hàm)([danh sach tham so]);
Ý nghĩa của các thành phần trong khai báo con trỏ hàm giống như đối với khai báo hàm.
Một con trỏ hàm chỉ có thể nhận giá trị là tên của các hàm có cùng kiểu giá trị trả về và kiểu giá trị của các tham số.
ví dụ:
int f_ptr1( int ); chỉ có thể lấy giá trị của các hàm một tham số kiểu nguyên int và có giá trị trả về cũng là kiểu int
trong khi đó con trỏ hàm: void f_ptr2(int, flloat); thì có thể nhận giá trị là tên các hàm có kiểu giá trị trả về là void và có hai tham số, trong đó tham số thứ nhất có kiểu nguyên int còn tham số thứ hai kiểu thực float.

3. Các chú ý khi dùng hàm con trỏ:
- Các hàm có thể trở thành đối tượng được gọi trong hàm khác nên khai báo trước.
- Khi gọi một hàm bằng con trỏ hàm f cần phải có dấu ngoặc, hàm được gọi theo kiểu f (danh sách các tham số nếu có )
- Không có sự khác biệt nào giữa việc gọi bằng tên của hàm và gọi bằng con trỏ hàm.

love1132
05-01-2010, 12:09 PM
bạn có tài liệu phần này ko? post lên cho mình dc ko? thanks nha

nguyenvansp09
30-10-2010, 10:11 PM
Haha..không biết có bác sv su phạm nào vào đây search bài hok nữa..em nè mấy bác

utkunglt
30-10-2010, 10:59 PM
mình nghĩ nếu đã dùng con trỏ thì nên xem bài viết này: Memory - Bộ nhớ | Thảo luận về cách chống leakMemory (http://forums.congdongcviet.com/showthread.php?t=14812)

và mình nghĩ còn thêm cái này nữa,(tai liệu nhiều mà bài tập cung nhìu, hok co thời gian ngâm cứu lun T_T)
khi nào thì sử dụng Con trỏ (http://forums.congdongcviet.com/showthread.php?t=26367&page=4)