函数声明不是原型
我有一个我创build的图书馆,
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); }
当我试图编译这个程序时,我得到以下错误:
从myprogram.c包含的文件中:1 mylib.h:2警告:函数声明不是原型
我正在使用: 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 ++中,它们意味着同样的事情。 我build议你在没有参数的情况下一直使用void
。
如果你有一个variablesa
, extern int a;
是告诉编译器a
是一个可能存在于不同的翻译单元中的符号(C编译器代表源文件)的一种方法,直到链接时才解决它。 另一方面,作为函数名的符号无论如何都是在链接时解决的。 存储类说明符( extern
, static
)的含义只影响其可见性, extern
是默认值,所以extern
实际上是不必要的。
我build议删除extern
,这是无关的,通常省略。
快速回答:将int testlib()
更改为int testlib(void)
以指定函数不带任何参数。
原型是根据定义的函数声明来指定函数参数的types。
非原型函数声明像
int foo();
是一种旧式的声明,没有指定参数的数量或types。 (在1989年的ANSI C标准之前,这是这种语言中唯一可用的函数声明)。你可以用任意数量的参数调用这样一个函数,编译器不需要抱怨 – 但是如果调用与定义不一致,你的程序有不确定的行为。
对于具有一个或多个参数的函数,可以在声明中指定每个参数的types:
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
需要一些未指定但固定数量和types的参数。
如果将()
更改为(void)
则声明将成为原型。
一个原型的优点是,如果你意外testlib
用一个或多个参数调用testlib
,编译器将诊断错误。
(C ++的规则略有不同,C ++没有旧式的函数声明,而空括号表示一个函数没有参数,C ++支持(void)
语法与C一致。但是除非你特别需要你的代码编译为C和C ++,你应该使用C ++中的()
和C中的(void)
语法)
尝试:
extern int testlib(void);