4

私はちょうど読んだ: Cでのこれらの関数定義の違いについての「C void 引数」 :

int f(void)

int f()

2 番目の形式は、任意の数のパラメーターを受け取る整数を返す関数を意味することを理解した上で、これらの未知のパラメーターに実際にアクセスして使用するにはどうすればよいのでしょうか?

サンプルコードと説明が欲しいです。

また、私は C の Varargs のメカニズム ( va_argva_end、関数を使用) を知っており、このメカニズムと上記の形式の違いva_startについて聞いてうれしいです。f()

本当にありがとうございました!

4

4 に答える 4

7

2 番目のバージョンは、可変数のパラメーターを受け入れず、固定 (ただし未指定) の一連のパラメーターを受け入れます。実際には、関数を宣言しますが、関数のプロトタイプは作成しません。そのため、関数の呼び出しは有効な型についてチェックされません。コンパイラが関数の最初の呼び出しを調べ、最初の呼び出しで見つかった型に対して他の呼び出しをチェックするのは一般的です。

このため、 を省略した場合#include <stdio.h>、 の最初の呼び出しprintfは受け入れられますがprintf、異なる型で を呼び出すとエラーが発生します。例えば。

int main() {
    printf("hello");        //<--- accepted, compiler may assume `int printf(char *);`
    printf("%s", "world");  //<--- error, type mismatch
}

関数が変数を受け入れるようにするには、少なくとも 1 つの固定パラメーターと token が必要...です。

int f (int first, ...);

stdarg.hヘッダー ファイルを含める必要があります。また、関数はマクロを使用してパラメーターにアクセスできます。

void f (int c,...){
    va_list ap;
    va_start(ap, c);
    for(;c--;)
        printf("%d", va_arg(ap,int));
    va_end (ap);
}

残りの引数の数を固定引数にすると便利です。また、何らかの方法で各引数の型を決定する必要があります。この例では、それらはすべて であると想定されていますint

于 2013-09-13T18:08:40.033 に答える
4
 int f(void);

引数を取らず、結果fを返す関数として宣言しますが、int

 int f();

f固定されているが指定されていない数と型の引数を取る (そしてもちろん結果を返す) 関数として宣言しintます。

そのような宣言が与えられた場合、実際にパラメーターを定義する定義がどこかになければなりません。パラメータを取らない場合は、次のように定義できます。

int f() {
    return 42;
};

2 つのパラメータを取る場合はint、次のように定義できます。

int f(int x, int y) {
    return x + y;
}

どちらの定義も と互換性がありますint f();が、最初のものだけが と互換性がありint f(void)ます。

パラメーターの型を指定する関数宣言、または特殊なケースとしてvoidキーワードを使用してパラメーターがないことを指定する関数宣言は、プロトタイプです。古いスタイルの宣言など、これを行わない関数宣言。int f();

プロトタイプをサポートしていない数十年前の ANSI 以前のコンパイラを使用している場合や、非常に古いコードを維持していて、それを更新する時間や他のリソースがない場合を除き、使用しない理由はありません。プロトタイプ。プロトタイプを表示せずに関数を呼び出す場合でも、正しい数と型の引数を渡す必要があります。違いは、呼び出しが正しくないかどうかをコンパイラが判断できないことです。

(変数の数と型の引数を取る関数を定義できますprintf。これはその例です。これは, ...表記法を使用して行われます。関数自体は<stdarg.h>、引数を処理するために で定義された機能を使用します。しかし、それは宣言とは関係ありません。あなたの質問に示されています。)

廃止された古いスタイルの関数宣言と定義を使用した小さなプログラムを次に示します。

#include <stdio.h>
#include <stdlib.h>

int add();

int main(argc, argv)
int argc;
char **argv;
{
    if (argc == 3) {
        /* NOTE: atoi() does no error checking */
        printf("sum = %d\n", add(atoi(argv[1]), atoi(argv[2])));
    }
    else {
        fprintf(stderr, "Usage: %s x y\n", argv[0]);
        exit(EXIT_FAILURE);
    }
}

int add(x, y)
int x, y;
{
    return x + y;
}

add(1, 2, 3, 4)orを書いた場合add("foo", "bar")、コンパイラはエラーをキャッチしなかったことに注意してください。プログラムは単に誤動作したでしょう。

以下は、最新の関数宣言と定義を使用した同等のプログラムです。

#include <stdio.h>
#include <stdlib.h>

int add(int x, int y);

int main(int argc, char **argv) {
    if (argc == 3) {
        /* NOTE: atoi() does no error checking */
        printf("sum = %d\n", add(atoi(argv[1]), atoi(argv[2])));
    }
    else {
        fprintf(stderr, "Usage: %s x y\n", argv[0]);
        exit(EXIT_FAILURE);
    }
}

int add(int x, int y) {
    return x + y;
}

可視プロトタイプは、コンパイラが不正な呼び出しを診断できることを意味します。

于 2013-09-13T18:47:50.333 に答える