2008-09-03 41 views
129

Tôi có một thư viện tôi tạo ra,khai chức năng không phải là một nguyên mẫu

mylib.c:

#include <mylib.h> 
int 
testlib() { 
    printf("Hello world\n"); 
    return (0); 
} 

mylib.h:

#include <stdio.h> 
extern int testlib(); 

Trong chương trình của tôi , Tôi đã cố gọi hàm thư viện này:

myprogram.c:

#include <mylib.h> 

int 
main (int argc, char *argv[]) { 
    testlib(); 
    return (0); 
} 

Khi tôi cố gắng để biên dịch chương trình này tôi nhận được lỗi sau:

In file included from myprogram.c:1 
mylib.h:2 warning: function declaration isn't a prototype

Tôi đang sử dụng: gcc (GCC) 3.4.5 20051201 (Red Hat 3.4.5-2)

Câu hỏi của tôi là, là những gì cách thích hợp để tuyên bố một nguyên mẫu chức năng?

+1

Xóa extern khỏi khai báo trong mylib.h Đặc biệt nếu bạn đang viết một chương trình C thuần túy, thì bên ngoài tuyên bố là không cần thiết ở đó. –

Trả lời

274

Trong C int foo()int foo(void) là chức năng khác nhau. int foo() chấp nhận một số lượng đối số tùy ý, trong khi int foo(void) chấp nhận 0 đối số. Trong C++ chúng có ý nghĩa tương tự. Tôi khuyên bạn nên sử dụng void một cách nhất quán khi bạn có nghĩa là không có đối số.

Nếu bạn có một biến a, extern int a; là một cách để nói với trình biên dịch rằng a là một biểu tượng rằng có thể có mặt trong một đơn vị dịch thuật khác nhau (C biên dịch nói cho file nguồn), không giải quyết được nó cho đến khi thời gian liên kết . Mặt khác, các ký hiệu là các tên hàm vẫn được giải quyết tại thời gian liên kết. Ý nghĩa của trình chỉ định lớp lưu trữ trên một hàm (extern, static) chỉ ảnh hưởng đến khả năng hiển thị của nó và extern là mặc định, vì vậy extern thực sự là không cần thiết.

Tôi khuyên bạn nên xóa extern, không liên quan và thường bị bỏ qua.

+5

Sử dụng '(void)' * trong C * để chỉ ra rằng một hàm không có đối số. Trong C++, trừ khi bạn đặc biệt cần mã của bạn để biên dịch cả C và C++, chỉ cần sử dụng '()'. –

17

Hãy thử:

extern int testlib(void); 
+27

-1: Không giải thích gì. –

+17

+1: Trả lời chính xác câu hỏi. – harper

37

Trả lời nhanh: thay đổi int testlib() thành int testlib(void) để chỉ định rằng hàm không có đối số.

A nguyên mẫu theo định nghĩa là khai báo hàm xác định loại (s) của đối số của hàm.

Một khai báo hàm phi nguyên mẫu như

int foo(); 

là một tuyên bố kiểu cũ mà không ghi rõ số điện thoại hoặc các loại đối số. (Trước tiêu chuẩn ANSI C 1989, đây là kiểu khai báo hàm duy nhất có sẵn trong ngôn ngữ.) Bạn có thể gọi một hàm như vậy với bất kỳ số lượng đối số tùy ý nào, và trình biên dịch không bắt buộc phải phàn nàn - nhưng nếu cuộc gọi không nhất quán với định nghĩa , chương trình của bạn có hành vi không xác định.

Đối với một hàm mang theo một hoặc nhiều đối số, bạn có thể chỉ định kiểu của mỗi tham số trong khai báo:

int bar(int x, double y); 

Chức năng không có đối số là một trường hợp đặc biệt. Một cách logic, dấu ngoặc rỗng sẽ là một cách tốt để xác định rằng một cuộc tranh cãi nhưng cú pháp đó là đã được sử dụng cho các tờ khai chức năng kiểu cũ, vì vậy ban ANSI C phát minh ra một cú pháp mới sử dụng void keyword:

int foo(void); /* foo takes no arguments */ 

Hàm định nghĩa (bao gồm mã cho chức năng thực sự thực hiện) cũng cung cấp khai báo . Trong trường hợp của bạn, bạn có điều gì đó tương tự như:

int testlib() 
{ 
    /* code that implements testlib */ 
} 

Điều này cung cấp tuyên bố không nguyên mẫu cho testlib. Như một định nghĩa, điều này nói với trình biên dịch rằng testlib không có tham số, nhưng như là một khai báo, nó chỉ nói với trình biên dịch rằng testlib có một số không xác định nhưng cố định và kiểu (s) của đối số.

Nếu bạn thay đổi () thành (void) tuyên bố trở thành mẫu thử nghiệm.

Lợi thế của nguyên mẫu là nếu bạn vô tình gọi testlib với một hoặc nhiều đối số, trình biên dịch sẽ chẩn đoán lỗi.

(C++ có các quy tắc hơi khác nhau. C++ không có khai báo hàm kiểu cũ và dấu ngoặc đơn trống có nghĩa là hàm không có đối số. C++ hỗ trợ cú pháp (void) cho tính nhất quán với C. Nhưng trừ khi bạn cần mã để biên dịch cả C và C++, có lẽ bạn nên sử dụng số () trong C++ và cú pháp (void) trong C.)

Các vấn đề liên quan