2016-09-14 27 views
0

私はKR Cの本を読んでいますが、私は理解できない関数定義に直面しています。それは87ページのqsort()の機能です。それはqsort()関数内swap()関数を宣言:Cの関数の中で関数を宣言する

void qsort(args) 
{ 
... 
void swap(arguments); 
... 
swap(a,b); 
} 

void swap(arguments){ 
... 
} 

swap()関数は、関数の外で宣言すべきではありませんか?なぜ内部に宣言するのですかqsort()機能?

+3

宣言されていない関数は使用できません。使用する前に宣言し宣言が有効である限り、宣言する場所は特に重要ではありません。 – Tibrogargan

+0

スコープが定義されているブロック内に限定されていませんか?この場合、 'swap()'は 'qsort()'関数内でのみ有効です – Arash

+0

@Arashはい。そして、それが定義された後のファイルの部分でも、もちろんです。脱調は宣言であるから。 – hyde

答えて

7

あなたはK & R Cプログラミング言語、おそらくANSI Cを使用した第2版を読んでいると思いますか? https://hassanolity.files.wordpress.com/2013/11/the_c_programming_language_2.pdfにはPDFがあり、87ページにはクイックソートアルゴリズムを使用した再帰の説明があります。

様々C規格https://en.wikipedia.org/wiki/ANSI_Cを比較し、対照的なこのウィキペディアのトピックを参照してください

Second Editionの著作権はそこに良い材料の1988年たくさんあるとしてK & RCの本は古いスタイルのCですが、それは視点から読まれる必要がありますより古いスタイルであり、C標準はANSI C以降に変更されています。主なものは、コンパイラがエラーと警告として宣言しているものに関するより優れた仕様です。 ANSI Cでは、現代のC標準ではもはや受け入れられないものが完全に受け入れられました。多くの研究は、Cプログラミング言語仕様を強化し、いくつかの余分なキーワードと構文を提供することによって、コンパイラによるより優れた静的チェックを提供しようとしています。

swap()の前方宣言があるか、関数が実際に使用される前にそのソースコードを含む関数の定義が現れるはずです。これにより、Cコンパイラは、可能な使用エラーをチェックするために、関数の使用法をその宣言または定義と照らし合わせてチェックすることができます。

ただし、Cプログラミング言語の場合、関数を定義または宣言する前に関数を使用すると、Visual Studio 2013 warning C4013: 'swap' undefined; assuming extern returning intからこの警告などの警告が表示されます。

最新のバージョンclanggccが気に入っており、Visual Studio 2015もC11の実装を開始しました。いくつかのコンパイラは、警告を改善したり、警告のいくつかの種類をエラーに変えたりするための追加オプションを提供しています。

たとえば、次のソースコードをtestit.cファイル(Cソースコードの.cファイル拡張子に注意してください)に入れ、Visual Studio 2013で4の警告レベルを使用してコンパイルすると、警告は表示されますがエラーは発生しません。 Visual Studioは、C言語の標準とルールを使用してこれをCソースとしてコンパイルします。これは、同じ構文の場合でもC++のものよりも緩いです。

このソースの2つの異なるバージョンをコンパイルしました.1行目の前方宣言がコメントアウトされ、1行目がコメント解除されています。 Visual StudioのCコンパイラが、前方宣言なしで関数を使用できるようにするという警告から注意してください。

2行目の前方宣言の2番目の実行でコメントが外されているときに、関数スコープ内の関数の前方宣言を置くことに関する警告があります。warning C4210: nonstandard extension used : function given file scope

2回目の実行で前方宣言を使用すると、コンパイラは使用可能なエラーを特定して警告を出し、ある場合には実際のエラーを発行できます。

引数の数は、最初のコンパイルと2番目のコンパイルでは異なりますが、2番目のコンパイルでのみ異なります。フォワード宣言はコメント化されておらず、追加の引数についての警告が表示されます。

int func1() {      // line 1 
// int swap(int a, int b);   // line 2, forward declaration for function swap 

    int j = swap(1, 2); 

    return 0; 
} 

int func2() {       // line 9 
    struct { 
     int a; 
     int b; 
     int c; 
    } mm = { 0 }; 

    int k = swap(4, 5, 8);    // line 16 

    float ff = swap(4.0, 5.0, 8.0); // line 18 

    int k2 = swap(mm, 2, 3);   // line 20 

    return 1; 
} 

int swap(int a, int b) {    // line 25 
    return a + b; 
} 

警告は、次のとおりです。

1>------ Build started: Project: ConsoleApplication3, Configuration: Debug Win32 ------ 
1> testit.c 
1>c:\users\projects\consoleapplication3\testit.c(4): warning C4013: 'swap' undefined; assuming extern returning int 
1>c:\users\projects\consoleapplication3\testit.c(4): warning C4189: 'j' : local variable is initialized but not referenced 
1>c:\users\projects\consoleapplication3\testit.c(18): warning C4244: 'initializing' : conversion from 'int' to 'float', possible loss of data 
1>c:\users\projects\consoleapplication3\testit.c(16): warning C4189: 'k' : local variable is initialized but not referenced 
1>c:\users\projects\consoleapplication3\testit.c(20): warning C4189: 'k2' : local variable is initialized but not referenced 
1>c:\users\projects\consoleapplication3\testit.c(18): warning C4189: 'ff' : local variable is initialized but not referenced 
1> ConsoleApplication3.vcxproj -> C:\Users\Projects\Debug\ConsoleApplication3.exe 

場合、私はその後、コメントを解除し、私はエラーと一緒に警告の次のコンパイラの出力を参照してください機能swap()のための前方宣言:今

1>------ Build started: Project: ConsoleApplication3, Configuration: Debug Win32 ------ 
1> testit.c 
1>c:\users\projects\consoleapplication3\testit.c(2): warning C4210: nonstandard extension used : function given file scope 
1>c:\users\projects\consoleapplication3\testit.c(4): warning C4189: 'j' : local variable is initialized but not referenced 
1>c:\users\projects\consoleapplication3\testit.c(16): warning C4020: 'swap' : too many actual parameters 
1>c:\users\projects\consoleapplication3\testit.c(18): warning C4244: 'function' : conversion from 'double' to 'int', possible loss of data 
1>c:\users\projects\consoleapplication3\testit.c(18): warning C4020: 'swap' : too many actual parameters 
1>c:\users\projects\consoleapplication3\testit.c(18): warning C4244: 'initializing' : conversion from 'int' to 'float', possible loss of data 
1>c:\users\projects\consoleapplication3\testit.c(20): error C2440: 'function' : cannot convert from '' to 'int' 
1>c:\users\projects\consoleapplication3\testit.c(20): warning C4024: 'swap' : different types for formal and actual parameter 1 
1>c:\users\projects\consoleapplication3\testit.c(20): warning C4020: 'swap' : too many actual parameters 

C++プログラミング言語は異なり、このような緩みを許さない。 C++はC言語と歴史を共有していますが、C++は関連する言語とは異なります。

同じソースをファイルtestit2.cppにコピーしてコンパイルすると、別のエラーが表示されます。

最初に、swap()の前方宣言がコメントアウトされています。

1> testit2.cpp 
1>c:\users\projects\consoleapplication3\testit2.cpp(4): error C3861: 'swap': identifier not found 
1>c:\users\projects\consoleapplication3\testit2.cpp(16): error C3861: 'swap': identifier not found 
1>c:\users\projects\consoleapplication3\testit2.cpp(18): error C3861: 'swap': identifier not found 
1>c:\users\projects\consoleapplication3\testit2.cpp(20): error C3861: 'swap': identifier not found 

また、前方宣言のコメントを外してください。

1> testit2.cpp 
1>c:\users\projects\consoleapplication3\testit2.cpp(4): warning C4189: 'j' : local variable is initialized but not referenced 
1>c:\users\projects\consoleapplication3\testit2.cpp(16): error C3861: 'swap': identifier not found 
1>c:\users\projects\consoleapplication3\testit2.cpp(18): error C3861: 'swap': identifier not found 
1>c:\users\projects\consoleapplication3\testit2.cpp(20): error C3861: 'swap': identifier not found 

そして、それは今、ライン1となるように、私は、ファイルスコープに機能func1()の範囲外swap()の前方宣言を移動した場合、最後に、私は、次の、異なるエラーが表示されます。

1> testit2.cpp 
1>c:\users\projects\consoleapplication3\testit2.cpp(4): warning C4189: 'j' : local variable is initialized but not referenced 
1>c:\users\projects\consoleapplication3\testit2.cpp(16): error C2660: 'swap' : function does not take 3 arguments 
1>c:\users\projects\consoleapplication3\testit2.cpp(18): error C2660: 'swap' : function does not take 3 arguments 
1>c:\users\projects\consoleapplication3\testit2.cpp(20): error C2660: 'swap' : function does not take 3 arguments 
+1

K&R第2版は、「ANSI C」(C90を意味する)の後ろにはほとんどありません。つまり、Visual Studioを使用して最新のC標準への準拠を示すことは最良のアイデアではありません。プロトタイプなしでVSで関数を使用できる理由は、VS Cコンパイラが古くなっていて、準拠していないためです。最新のCプログラミングをしたい場合は、K&RブックとVisual Studioの両方をクリアにしてください。 – Lundin