4

C99 標準のデフォルト引数昇格について質問があります。「C Programming - A Modern Approach, 2nd Edition」という本の中で、私は次のことを読みました。

引数の変換:

[...]

1)呼び出しの前に、コンパイラーがプロトタイプに遭遇しました。[...]

2)コンパイラは、呼び出しの前にプロトタイプに遭遇していません。コンパイラはデフォルトの引数昇格を実行します: (1)float引数は に変換されdoubleます。(2) 整数昇格が実行され、charshort引数が に変換されintます。( C99 では、整数昇格が実行されます。 )

数行先には、呼び出す前に関数のプロトタイプまたは定義がない例が示されています。以下のようにコメントされています。

もちろん、より良い解決策は、square呼び出す前に のプロトタイプを提供することです。C99 では、square最初に関数の宣言または定義を提供せずに呼び出すとエラーになります。

この二つの筆記体の文章は相反するものではないですか。つまり、C99 が以前の宣言/定義なしで関数を呼び出すことを禁止している場合、その種の関数呼び出しでプロモーションをどのように決定できますか?

4

3 に答える 3

7

いいえ、矛盾していません。

宣言は必ずしもプロトタイプではありません。

int f();

関数を宣言しますfが、引数の型について何も知られていないため、プロトタイプではありません。

int (a)
 in a;
{
 ...
}

は定義ですが、プロトタイプでもありません。

于 2012-08-17T15:55:25.613 に答える
2

C99 では、プロトタイプを持たない関数を呼び出すことは禁止されていません。

コードまたはその呼び出しを投稿していないため、詳細を説明することはできませんsquare()が、おそらく、呼び出しで引数に行われた昇格square()により、実際に宣言されているものとは異なる型が関数に渡されている可能性があります実装中。

それは未定義の動作を引き起こし、エラーになります。

例えば:

// in foo.c:

int foo(void)
{ 
    char x = 42;

    return square(x); // x is promoted to int, but is wrong
}


// in bar.c

#include <stdio.h>
void bar(int x)
{ 
    square( &x); // this call is fine -  what is being passed is what square() expects
    printf("The result is %d\n", x);
}


// in square.c

void square( int* p)
{
    *p *= *p;
    return;
}

また、square()が type の引数を持つようにパラメーターを宣言するプロトタイプで定義されている場合char、プロトタイプが呼び出しコードによって「認識」されていない限り、それを正しく呼び出す方法はありません。このような場合、引数は に昇格されるためintです。

于 2012-08-17T15:58:23.083 に答える
1

C99で事前に宣言または定義を提供せずに関数を呼び出すエラーであることについては何も見つかりません。

最後に、int のデフォルトの戻り値の型が想定されなくなったようです。つまり、宣言foo(int a);は C99 以前では許可されていますが、C99 ではエラーになります。C99より前のことを意味しますint foo(int a);

于 2012-08-17T17:02:33.373 に答える