";
return 0;
mylib.h:12#include "/>

关于C#:function声明不是原型

关于C#:function声明不是原型

function declaration isn't a prototype

我有一个我创建的图书馆

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编译器表示源文件),请在解析前将其解析。链接时间。另一方面,作为函数名称的符号无论如何都在链接时解析。函数(externstatic)上的存储类说明符的含义仅影响其可见性,而extern是默认值,因此实际上不需要extern

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


快速解答:将int testlib()更改为int testlib(void)以指定该函数不接受任何参数。

根据定义,原型是一个函数声明,该声明指定函数自变量的类型。

非原型函数声明,例如

1
int foo();

是一种旧式声明,未指定参数的数量或类型。 (在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);


推荐阅读