2008-09-03 119 views
129

我有我创建了一个库,函数声明不是一个原型

mylib.c:

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

mylib.h:

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

在我的计划,我已经尝试调用这个库中的函数:

myprogram.c:

#include <mylib.h> 

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

当我尝试编译这个程序,我得到以下错误:

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

我使用:gcc (GCC) 3.4.5 20051201 (Red Hat 3.4.5-2)

我的问题是,什么是声明函数原型的正确方法?

+1

从mylib.h中的声明中删除extern特别是如果你正在编写纯C程序,那么extern宣言是不必要的。 – 2008-09-03 17:16:55

回答

274

在C int foo()int foo(void)是不同的函数。 int foo()接受任意数量的参数,而int foo(void)接受0个参数。在C++中,它们意味着同样的事情。我建议你一直使用void,当你的意思是没有参数。

如果你有一个变量aextern int a;是一种方式来告诉编译器a是可能存在于不同的翻译单元(C编译器源文件说吧)的象征,不解决它,直到链接时。另一方面,作为函数名的符号无论如何都是在链接时解决的。上的功能(externstatic)存储类说明的意义仅影响其知名度和extern是默认的,所以extern实际上是不必要的。

我建议去掉extern,它是多余的,通常省略。

17

尝试:

extern int testlib(void); 
+27

-1:没有任何解释。 – 2013-03-23 12:16:28

+17

+1:正确回答了问题。 – harper 2013-12-30 17:18:13

37

快速回答:更改int testlib()int testlib(void)以指定函数不带参数。

原型是通过定义一个函数声明,指定函数的参数(一个或多个)的类型(一个或多个)。

int foo(); 

非原型函数声明是一个老式的声明没有指定参数的数目和类型。 (在1989 ANSI C标准之前,这是该语言中唯一可用的函数声明。)可以使用任意数量的参数调用此函数,并且编译器无需投诉 - 但如果呼叫与定义不一致,您的程序具有未定义的行为。

对于接受一个或多个参数的函数,你可以在声明中指定每个参数的类型:

不带参数
int bar(int x, double y); 

功能是一种特殊情况。从逻辑上讲,空括号本来指定的说法,但这种语法已经在使用旧式函数声明的好方法,所以ANSI C委员会使用void关键字发明了一种新的语法:

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

函数定义(其中包括什么功能实际上不会代码)也提供了声明。你的情况,你有类似的东西:

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

这为testlib非原型声明。作为定义,这告诉testlib没有参数编译器,但作为一个声明,它只是告诉该testlib需要的参数一些未指定的,但固定数量和类型的编译器。

如果将()更改为(void)该声明将成为原型。

原型的优点是,如果您不小心通过一个或多个参数调用testlib,编译器将诊断错误。 C++支持(void)语法与C的一致性。但是除非你特别需要你的语言,否则你不需要代码编译为C和C++,你应该使用C++中的()和C中的(void)语法。)