6

最近、ファイルを開くプログラムを書いているときに質問を受けました。

私の質問を明確に説明させてください。ここでは、open呼び出しを例に取っています。

ファイルを作成するには:

open("file_name", O_CREAT, 0766); //passing 3 parametrs

ファイルを開くには:

open("file_name", O_RDWR); //only 2 arguments.

次に、この点を明確に観察しましたが、これも機能しmain()ます。

main(void) //worked
main(int argc, char **argv); //worked
main(int argc) //worked and it's doesn't give an error like "too few arguments". 
main() //worked 

では、これらのオプションの引数を作成するにはどうすればよいでしょうか? コンパイラはこれらのプロトタイプをどの程度正確に検証できますか? 可能であれば、サンプルプログラムを書いてください。

4

2 に答える 2

7

関数はopen可変個引数関数として宣言されています。次のようになります。

#include <stdarg.h>

int open(char const * filename, int flags, ...)
{
    va_list ap;
    va_start(ap, flags);

    if (flags & O_CREAT)
    {
        int mode = va_arg(ap, int);
        // ...
    }

    // ...

    va_end(ap);
}

それ以降の引数は、実際に存在することを示さない限り消費されません。

にも同じ構造が使用されprintfます。

(char const *, int)可能な 2 つのシグネチャはとだけであるため、マニュアルは常にこれを明示しているわけではありません(char const *, int, int)。そのため、関数が実際に可変引数を受け入れることを明らかにしてもほとんど意味がありません。(これは、次のようなものをコンパイルしてテストできますopen("", 1, 2, 3, 4, 5, 6)。)

于 2013-10-06T18:05:26.520 に答える
1

いずれの場合も、varargs 関数は、固定引数から、可変引数がいくつあるかを何らかの方法で判別できなければなりません。たとえば、printf()関数のファミリは、書式文字列を使用して引数の数と型を決定します。このexecl()関数は、センチネル (null ポインター) を使用して、引数リストの末尾をマークします。センチネルの代わりにカウントを使用することも可能です (しかし、そうする場合、varargs 以外の関数のカウントと配列は、より良くはないにしても、同様に機能する可能性があります。 count と引数のリスト)。open()関数はフラグ ビットの 1 つを使用して、モードが存在するかどうかを判断します — Kerrek SB回答を参照してください。

main()関数は特殊なケースです。実装 (コンパイラ) は、そのプロトタイプを宣言することを禁止されており、少なくとも 2 つの形式を受け入れる必要があります。

int main(int argc, char **argv);
int main(void);

またはそれらの同等物。他の形式も受け入れる場合があります。C での 3 番目の環境変数の使用は何ですか?main()を参照してください1つの一般的なフォーム。C では (C++ ではなく)、標準コンパイラは他の戻り値の型を文書化できます — Microsoft はvoidVS 2008 以降の有効な戻り値の型として文書化しています。

の実装提供のプロトタイプがないためmain()、コンパイラは の宣言/定義を公式に拒否することはできませmain()んが、認識できないフォームにコメントを渡す可能性があります (GCC は型をmain()返さない関数にコメントしますint。たとえば、 )。

于 2013-10-06T18:41:37.237 に答える