函数声明不是原型。

时间:2021-08-13 17:49:03

I have a library I created,

我创建了一个库,

mylib.c:

mylib.c:

#include <mylib.h>
int
testlib() {
    printf("Hello world\n");
    return (0);
}

mylib.h:

mylib.h:

#include <stdio.h>
extern int testlib();

In my program, I've attempted to call this library function:

在我的程序中,我尝试调用这个库函数:

myprogram.c:

myprogram.c:

#include <mylib.h>

int
main (int argc, char *argv[]) {
    testlib();
    return (0);
}

When I attempt to compile this program I get the following error:

当我试图编译这个程序时,我得到了以下错误:

In file included from myprogram.c:1
mylib.h:2 warning: function declaration isn't a prototype

I'm using: gcc (GCC) 3.4.5 20051201 (Red Hat 3.4.5-2)

我正在使用:gcc (gcc) 3.4.5 20051201(红帽3.4.5-2)

My question is, what is the proper way to declare a function prototype?

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

3 个解决方案

#1


280  

In C int foo() and int foo(void) are different functions. int foo() accepts an arbitrary number of arguments, while int foo(void) accepts 0 arguments. In C++ they mean the same thing. I suggest that you use void consistently when you mean no arguments.

在C中,foo()和int foo(void)是不同的函数。int foo()接受任意数量的参数,而int foo(void)接受0个参数。在c++中,它们的意思是一样的。我建议你在没有争论的时候一致地使用void。

If you have a variable a, extern int a; is a way to tell the compiler that a is a symbol that might be present in a different translation unit (C compiler speak for source file), don't resolve it until link time. On the other hand, symbols which are function names are anyway resolved at link time. The meaning of a storage class specifier on a function (extern, static) only affects its visibility and extern is the default, so extern is actually unnecessary.

如果你有一个变量a,外部int a;是一种告诉编译器a是可能存在于不同翻译单元中的符号(C编译器为源文件说话)的一种方法,在链接时间之前不要解析它。另一方面,函数名的符号在链接时也会被解析。存储类说明符对函数(外部、静态)的意义只影响它的可见性,而外部是默认的,所以外部是不必要的。

I suggest removing the extern, it is extraneous and is usually omitted.

我建议去掉外面的,它是无关的,通常省略。

#2


37  

Quick answer: change int testlib() to int testlib(void) to specify that the function takes no arguments.

快速回答:将int testlib()改为int testlib(void),以指定函数不接受参数。

A prototype is by definition a function declaration that specifies the type(s) of the function's argument(s).

原型是一个函数声明,它指定函数参数的类型(s)。

A non-prototype function declaration like

一个非原型的函数声明。

int foo();

is an old-style declaration that does not specify the number or types of arguments. (Prior to the 1989 ANSI C standard, this was the only kind of function declaration available in the language.) You can call such a function with any arbitrary number of arguments, and the compiler isn't required to complain -- but if the call is inconsistent with the definition, your program has undefined behavior.

是一种旧式声明,它没有指定参数的数量或类型。(在1989年ANSI C标准之前,这是语言中唯一可用的函数声明。)您可以使用任意数量的参数调用这样的函数,而编译器不需要抱怨——但是如果调用与定义不一致,您的程序就有未定义的行为。

For a function that takes one or more arguments, you can specify the type of each argument in the declaration:

对于一个使用一个或多个参数的函数,您可以在声明中指定每个参数的类型:

int bar(int x, double y);

Functions with no arguments are a special case. Logically, empty parentheses would have been a good way to specify that an argument but that syntax was already in use for old-style function declarations, so the ANSI C committee invented a new syntax using the void keyword:

没有参数的函数是特殊情况。从逻辑上来说,空括号是指定参数的好方法,但是这种语法已经用于旧式函数声明,因此ANSI C委员会使用void关键字创建了一个新的语法:

int foo(void); /* foo takes no arguments */

A function definition (which includes code for what the function actually does) also provides a declaration. In your case, you have something similar to:

函数定义(包括函数的实际操作代码)也提供了一个声明。在你的案例中,你有类似的东西:

int testlib()
{
    /* code that implements testlib */
}

This provides a non-prototype declaration for testlib. As a definition, this tells the compiler that testlib has no parameters, but as a declaration, it only tells the compiler that testlib takes some unspecified but fixed number and type(s) of arguments.

这为testlib提供了一个非原型声明。作为一个定义,它告诉编译器testlib没有参数,但是作为一个声明,它只告诉编译器testlib需要一些未指定的但是固定的数目和类型的参数。

If you change () to (void) the declaration becomes a prototype.

如果您更改()到(void),则声明将成为原型。

The advantage of a prototype is that if you accidentally call testlib with one or more arguments, the compiler will diagnose the error.

原型的优点是,如果您使用一个或多个参数意外地调用testlib,编译器将诊断错误。

(C++ has slightly different rules. C++ doesn't have old-style function declarations, and empty parentheses specifically mean that a function takes no arguments. C++ supports the (void) syntax for consistency with C. But unless you specifically need your code to compile both as C and as C++, you should probably use the () in C++ and the (void) syntax in C.)

(c++有稍微不同的规则。c++没有旧式的函数声明,空括号意味着函数没有参数。c++支持(void)语法以保持与C的一致性。但是,除非您特别需要您的代码来编译C和c++,您可能应该使用c++中的()和C语言中的(void)语法。

#3


18  

Try:

试一试:

extern int testlib(void);

#1


280  

In C int foo() and int foo(void) are different functions. int foo() accepts an arbitrary number of arguments, while int foo(void) accepts 0 arguments. In C++ they mean the same thing. I suggest that you use void consistently when you mean no arguments.

在C中,foo()和int foo(void)是不同的函数。int foo()接受任意数量的参数,而int foo(void)接受0个参数。在c++中,它们的意思是一样的。我建议你在没有争论的时候一致地使用void。

If you have a variable a, extern int a; is a way to tell the compiler that a is a symbol that might be present in a different translation unit (C compiler speak for source file), don't resolve it until link time. On the other hand, symbols which are function names are anyway resolved at link time. The meaning of a storage class specifier on a function (extern, static) only affects its visibility and extern is the default, so extern is actually unnecessary.

如果你有一个变量a,外部int a;是一种告诉编译器a是可能存在于不同翻译单元中的符号(C编译器为源文件说话)的一种方法,在链接时间之前不要解析它。另一方面,函数名的符号在链接时也会被解析。存储类说明符对函数(外部、静态)的意义只影响它的可见性,而外部是默认的,所以外部是不必要的。

I suggest removing the extern, it is extraneous and is usually omitted.

我建议去掉外面的,它是无关的,通常省略。

#2


37  

Quick answer: change int testlib() to int testlib(void) to specify that the function takes no arguments.

快速回答:将int testlib()改为int testlib(void),以指定函数不接受参数。

A prototype is by definition a function declaration that specifies the type(s) of the function's argument(s).

原型是一个函数声明,它指定函数参数的类型(s)。

A non-prototype function declaration like

一个非原型的函数声明。

int foo();

is an old-style declaration that does not specify the number or types of arguments. (Prior to the 1989 ANSI C standard, this was the only kind of function declaration available in the language.) You can call such a function with any arbitrary number of arguments, and the compiler isn't required to complain -- but if the call is inconsistent with the definition, your program has undefined behavior.

是一种旧式声明,它没有指定参数的数量或类型。(在1989年ANSI C标准之前,这是语言中唯一可用的函数声明。)您可以使用任意数量的参数调用这样的函数,而编译器不需要抱怨——但是如果调用与定义不一致,您的程序就有未定义的行为。

For a function that takes one or more arguments, you can specify the type of each argument in the declaration:

对于一个使用一个或多个参数的函数,您可以在声明中指定每个参数的类型:

int bar(int x, double y);

Functions with no arguments are a special case. Logically, empty parentheses would have been a good way to specify that an argument but that syntax was already in use for old-style function declarations, so the ANSI C committee invented a new syntax using the void keyword:

没有参数的函数是特殊情况。从逻辑上来说,空括号是指定参数的好方法,但是这种语法已经用于旧式函数声明,因此ANSI C委员会使用void关键字创建了一个新的语法:

int foo(void); /* foo takes no arguments */

A function definition (which includes code for what the function actually does) also provides a declaration. In your case, you have something similar to:

函数定义(包括函数的实际操作代码)也提供了一个声明。在你的案例中,你有类似的东西:

int testlib()
{
    /* code that implements testlib */
}

This provides a non-prototype declaration for testlib. As a definition, this tells the compiler that testlib has no parameters, but as a declaration, it only tells the compiler that testlib takes some unspecified but fixed number and type(s) of arguments.

这为testlib提供了一个非原型声明。作为一个定义,它告诉编译器testlib没有参数,但是作为一个声明,它只告诉编译器testlib需要一些未指定的但是固定的数目和类型的参数。

If you change () to (void) the declaration becomes a prototype.

如果您更改()到(void),则声明将成为原型。

The advantage of a prototype is that if you accidentally call testlib with one or more arguments, the compiler will diagnose the error.

原型的优点是,如果您使用一个或多个参数意外地调用testlib,编译器将诊断错误。

(C++ has slightly different rules. C++ doesn't have old-style function declarations, and empty parentheses specifically mean that a function takes no arguments. C++ supports the (void) syntax for consistency with C. But unless you specifically need your code to compile both as C and as C++, you should probably use the () in C++ and the (void) syntax in C.)

(c++有稍微不同的规则。c++没有旧式的函数声明,空括号意味着函数没有参数。c++支持(void)语法以保持与C的一致性。但是,除非您特别需要您的代码来编译C和c++,您可能应该使用c++中的()和C语言中的(void)语法。

#3


18  

Try:

试一试:

extern int testlib(void);