函数声明不是原型?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (32)

我有一个我创建的库,

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 ++中,它们意味着同样的事情。void当你的意思是没有参数时,我建议你一贯使用。

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

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

用户回答回答于

更改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)语法)

扫码关注云+社区