函数声明不是原型

时间:2008-09-03 17:08:18

标签: c gcc

我有一个我创建的库,

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)

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

3 个答案:

答案 0 :(得分:312)

在C int foo()int foo(void)中有不同的功能。 int foo()接受任意数量的参数,而int foo(void)接受0个参数。在C ++中,它们的意思相同。我建议您在没有参数的情况下始终使用void

如果你有一个变量aextern int a;是一种告诉编译器a是一个可能存在于不同翻译单元中的符号的方法(C编译器代表源代码)文件),直到链接时才解决它。另一方面,作为功能名称的符号无论如何都在链接时被解析。函数(externstatic)上的存储类说明符的含义仅影响其可见性,extern是默认值,因此extern实际上是不必要的。

我建议删除extern,这是无关的,通常会被省略。

答案 1 :(得分:43)

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

prototype 定义为一个函数声明,它指定函数参数的类型。

非原型函数声明,如

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 ++的规则略有不同.C ++没有旧式函数声明,空括号特意表示函数不带参数.C ++支持(void)语法与C一致。但是除非您特别需要将代码编译为C和C ++,否则您应该使用C ++中的()和C中的(void)语法。)

答案 2 :(得分:22)

尝试:

extern int testlib(void);