177

我有一个我创建的图书馆,

文件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)

声明函数原型的正确方法是什么?

4

3 回答 3

376

在 Cint foo()int foo(void)是不同的功能。int foo()接受任意数量的参数,同时int foo(void)接受 0 个参数。在 C++ 中,它们的含义相同。我建议您void在没有争论的情况下始终如一地使用。

如果你有一个 variable aextern int a;是一种告诉编译器这a是一个可能出现在不同翻译单元中的符号的方法(C 编译器代表源文件),在链接时间之前不要解析它。另一方面,作为函数名称的符号无论如何都会在链接时解析。extern函数( , )上的存储类说明符的含义static仅影响其可见性并且extern是默认值,因此extern实际上是不必要的。

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

于 2008-09-06T17:58:18.500 回答
58

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

于 2013-12-30T16:49:20.700 回答
24

尝试:

extern int testlib(void);
于 2008-09-03T17:11:31.527 回答