関数宣言はプロトタイプではありません


158

私が作成したライブラリがあります。

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)

私の質問は、関数プロトタイプを宣言する適切な方法は何ですか?


1
mylib.hの宣言からexternを削除します。特に純粋なCプログラムを作成している場合、extern宣言は必要ありません。
ライアンアハーン

回答:


333

C int foo()int foo(void)は異なる関数です。0 int foo()個の引数を受け入れ、任意の数の引数をint foo(void)受け入れます。C ++では同じ意味です。void引数がないことを意味する場合は、一貫して使用することをお勧めします。

変数がある場合aextern int a;それaは別の変換単位に存在する可能性があるシンボルであることをコンパイラーに伝える方法です(Cコンパイラーはソースファイルを読みます)。リンク時まで解決しないでください。一方、関数名であるシンボルはリンク時に解決されます。関数(externstatic)のストレージクラス指定子の意味は、その可視性にのみ影響しextern、デフォルトであるためextern、実際には不要です。

を削除することをお勧めしますextern。これは無関係であり、通常は省略されます。


9
(void) Cで使用て、関数が引数を取らないことを示します。C ++では、コードをCとC ++の両方としてコンパイルする必要がない限り、を使用します()
キース・トンプソン

49

簡単な答え:に変更int testlib()int testlib(void)て、関数が引数を取らないように指定します。

プロトタイプは、定義により、関数の引数(複数可)の指定タイプ(s)は、その関数の宣言です。

次のような非プロトタイプの関数宣言

int foo();

引数の数や型を指定しない旧式の宣言です。(1989 ANSI C標準以前は、これは言語で使用できる唯一の種類の関数宣言でした。)そのような関数は任意の数の引数で呼び出すことができ、コンパイラーは文句を言う必要はありませんが、呼び出しが定義と矛盾しています。プログラムに未定義の動作があります。

1つ以上の引数を取る関数の場合、宣言で各引数のタイプを指定できます。

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て1つ以上の引数を指定して呼び出した場合、コンパイラーがエラーを診断することです。

(C ++にはわずかに異なる規則があります。C++には古いスタイルの関数宣言がありません。空の括弧は、関数が引数を取らないことを具体的に意味します。C++はC (void)との一貫性のための構文をサポートします。 CおよびC ++として、おそらく()C ++ではinを、Cでは(void)構文を使用する必要があります。)


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.