質問
自分で作成したライブラリがありますが、
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);
}
このプログラムをコンパイルしようとすると、次のエラーが発生します。
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 コンパイラはソース ファイルを指します) に存在する可能性があるシンボルです。リンク時まで解決されません。一方、関数名であるシンボルはリンク時に解決されます。関数のストレージ クラス指定子の意味 (extern
, static
) はその可視性にのみ影響し、 extern
がデフォルトなので、 extern
実際には不要です。
を削除することをお勧めします extern
, 、無関係なので通常は省略されます。
他のヒント
素早い回答:変化 int testlib()
に int testlib(void)
関数が引数を取らないことを指定します。
あ プロトタイプ 定義上、これは関数の引数の型を指定する関数宣言です。
次のような非プロトタイプ関数宣言
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++ がサポートしているのは、 (void)
C との一貫性を保つための構文。ただし、特にコードを C と C++ の両方としてコンパイルする必要がない限り、おそらく、 ()
C++ では、 (void)
C の構文。)
試す:
extern int testlib(void);