我有一个我创建的图书馆
mylib.c:
1 2 3 4 5 6 7
| #include <mylib.h>
int
testlib() {
printf("Hello world
");
return (0);
} |
mylib.h:
1 2
| #include <stdio.h>
extern int testlib(); |
在我的程序中,我尝试调用此库函数:
myprogram.c:
1 2 3 4 5 6 7
| #include <mylib.h>
int
main (int argc, char *argv[]) {
testlib();
return (0);
} |
当我尝试编译该程序时,出现以下错误:
1 2
| 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)
我的问题是,声明函数原型的正确方法是什么?
在C中,int foo()和int foo(void)是不同的功能。 int foo()接受任意数量的参数,而int foo(void)接受0个参数。在C ++中,它们含义相同。我建议您在没有参数的情况下始终使用void。
如果您有变量a,则extern int a;是一种告诉编译器a是可能存在于其他翻译单元中的符号的一种方法(C编译器表示源文件),请在解析前将其解析。链接时间。另一方面,作为函数名称的符号无论如何都在链接时解析。函数(extern,static)上的存储类说明符的含义仅影响其可见性,而extern是默认值,因此实际上不需要extern。
我建议删除extern,它是多余的,通常被省略。
快速解答:将int testlib()更改为int testlib(void)以指定该函数不接受任何参数。
根据定义,原型是一个函数声明,该声明指定函数自变量的类型。
非原型函数声明,例如
是一种旧式声明,未指定参数的数量或类型。 (在1989年ANSI C标准之前,这是该语言中可用的唯一一种函数声明。)您可以使用任意数量的参数来调用这样的函数,并且编译器不需要抱怨-但是,如果调用与定义不一致,您的程序具有未定义的行为。
对于采用一个或多个参数的函数,可以在声明中指定每个参数的类型:
1
| int bar(int x, double y); |
没有参数的函数是一种特殊情况。从逻辑上讲,使用空括号可以指定一个参数,但该语法已用于旧式函数声明,因此ANSI C委员会使用void关键字发明了一种新语法:
1
| int foo(void); /* foo takes no arguments */ |
函数定义(包括函数实际执行的代码)也提供了声明。您的情况类似于:
1 2 3 4
| int testlib()
{
/* code that implements testlib */
} |
这为testlib提供了非原型声明。作为定义,它告诉编译器testlib没有参数,但是作为声明,它仅告诉编译器testlib接受一些未指定但固定数量和类型的参数。
如果将()更改为(void),则声明将成为原型。
原型的优势在于,如果您意外地使用一个或多个参数调用testlib,则编译器将诊断该错误。
(C ++的规则略有不同。C++没有旧式的函数声明,并且空括号特别意味着函数不带参数。C++支持(void)语法以与C保持一致。但是除非您特别需要代码以作为C和C ++进行编译,您可能应该在C ++中使用()和在C中使用(void)语法。)
尝试:
1
| extern int testlib(void); |