2011-08-21 34 views
22

Nói rằng tôi có chức năng này:Tại sao tôi có thể gọi một hàm thông qua một con trỏ với quá nhiều đối số?

int func2() { 
    printf("func2\n"); 
    return 0; 
} 

Bây giờ tôi tuyên bố một con trỏ:

int (*fp)(double); 

này phải trỏ đến một chức năng mà phải mất một lập luận double và trả về một int.

func2 KHÔNG có bất kỳ tranh cãi, nhưng vẫn còn khi tôi viết:

fp = func2; 
fp(2); 

(với 2 là chỉ là một số tùy ý), func2` được gọi một cách chính xác.

Tại sao lại như vậy? Không có ý nghĩa gì đối với số lượng tham số mà tôi khai báo cho một con trỏ hàm?

+0

Câu trả lời ngắn gọn là "tuyên bố một hàm không có đối số ... và sau đó cố tình chuyển một đối số ... là sai". – paulsm4

Trả lời

46

Vâng, có một ý nghĩa. Trong C (nhưng không phải trong C++), hàm được khai báo bằng một bộ ngoặc đơn trống có nghĩa là phải mất số tham số không xác định. Khi bạn làm điều này, bạn đang ngăn chặn trình biên dịch kiểm tra số lượng và loại đối số; đó là một sự lưu giữ từ trước khi ngôn ngữ C được chuẩn hóa bởi ANSI và ISO.

Không gọi hàm có số lượng và loại đối số phù hợp sẽ dẫn đến hành vi chưa xác định. Nếu bạn khai báo thay vì rõ ràng chức năng của bạn để tận zero thông số bằng cách sử dụng một danh sách tham số của void, sau đó trình biên dịch sẽ cung cấp cho bạn một cảnh báo khi bạn gán một con trỏ hàm của các loại sai:

int func1(); // declare function taking unspecified parameters 
int func2(void); // declare function taking zero parameters 
... 
// No warning, since parameters are potentially compatible; calling will lead 
// to undefined behavior 
int (*fp1)(double) = func1; 
... 
// warning: assignment from incompatible pointer type 
int (*fp2)(double) = func2; 
-4

Bạn cần phải tuyên bố một cách rõ ràng tham số, nếu không bạn sẽ nhận được hành vi không xác định :)

int func2(double x) 
{ 
    printf("func2(%lf)\n", x); 
    return 0; 
} 
Các vấn đề liên quan