11

K&R スタイルの関数宣言に慣れていません。

コンパイルに続いて、警告が表示されます(メインの戻り値に関連するだけです-Wall)が、使用される変数のデータ型は何ですか?

main(a, b, c, d){
    printf("%d", d);
}

foo(a, b){
     a = 2; 
     b = 'z';
}

これが以前に尋ねられた場合は、コメント セクションにリンクを提供してください。似たようなものは見つかりませんでした。

編集

これらを使用する難読化された C コードに出くわしました。
しかし、私は C プログラミングでそのような構文を使用しないことを保証します。

4

4 に答える 4

21

「K&R C」は、1978 年の Kernighan & Ritchie の著書「The C Programming Language」の初版で定義された言語を指します。

K&R (つまり、ANSI 以前) の C では、エンティティは通常、明示的な型なしで宣言でき、デフォルトで type になりますint。これは、C の祖先言語である B と BCPL にまでさかのぼります。

main(a,b,c,d){
    printf("%d", d);
}

これは、次とほぼ同等です。

int main(int a, int b, int c, int d) {
    printf("%d", d);
}

ANSI C (1989) および ISO C (1990) では、古い構文は有効でしたが廃止されましたが、1999 年の ISO C 標準では、"implicit int" ルールが廃止されました (古いスタイルの宣言と定義の構文は維持されています)。

ほぼ同等であると言ったことに注意してください。定義として見ると本質的に同じですが、宣言としてはパラメーターの型情報を提供しません。古いスタイルの定義では、引数の数または型が間違っている呼び出しを診断する必要はありません。それは未定義の動作です。プロトタイプが表示されている場合、引数の不一致はコンパイル時の診断をトリガーし、可能であれば、引数は暗黙的にパラメーターの型に変換されます。

これは の定義なので、main別の問題があります。標準では、 の 2 つの形式のみが指定されmainています (1 つは引数なし、もう 1 つは 2 つの引数、argcおよびargv)。実装は他の形式をサポートするかもしれませんが、4 つのint引数を持つものはそれらの 1 つではない可能性があります。したがって、プログラムの動作は未定義です。実際にdは、最初の呼び出しでガベージ値が含まれる可能性があります。(もちろん、C では の再帰呼び出しmainが許可されていますが、良い考えはほとんどありません。)

foo(a,b){
    a = 2;
    b = 'z';
}

これは、次とほぼ同等です。

int foo(int a, int b) {
    a = 2;
    b = 'z';
}

'z'(そして、は typeintではなく、 type であることに注意してくださいchar。)

繰り返しますが、古い形式ではパラメーターの型チェックが行われないため、次のような呼び出しを行います。

foo("wrong type and number of arguments", 1.5, &foo);

診断する必要はありません。

結論: K&R スタイルの関数宣言と定義がどのように機能するかを知っておくとよいでしょう。それらを使用する古いコードがまだあり、C2011 でもまだ有効です (ただし廃止されています) (ただし、「暗黙的な int」ルールはありません)。しかし、それらを使用するコードを作成する正当な理由はほとんどありません (非常に古いコンパイラを使用している場合を除きますが、それはまれであり、ますますまれになっています)。

しかし、C プログラミングでそのような構文を使用することはないと断言できます。

優秀な!

于 2013-08-24T19:36:53.447 に答える
6

K&R スタイルの関数定義では、パラメーターの型は、関数の「署名」自体と実際の関数本体の間に配置される専用の宣言セットによって指定されます。たとえば、この関数定義

void foo(a, b, c)
double a;
char b;
{
  ...
}

doubleタイプ、charおよびのパラメータを使用しますint。これは、実際に「暗黙の int」ルールが機能する場所と方法です。パラメーターcは上記の宣言リストで言及されていないため、 type を持つと想定されますint

他の回答では十分に明確にされていないと私が信じている重要な詳細に注意してください。パラメーターcに型intがあるのは、型が関数パラメーターリストにないためではなく、関数の「署名」に続く宣言子のシーケンスで言及されていないためです。 (関数本体の前)。K&R スタイルの宣言では、型は常に関数パラメーター リストから欠落しています (これは K&R 宣言の定義機能です) int

PS C99 は引き続き K&R スタイルの宣言をサポートしますが、C99 は「implicit int」ルールを禁止しているため、関数「signature」の後に宣言リスト内のすべての関数パラメーターを指定する必要があることに注意してください。そのため、上記の例は C99 ではコンパイルされません。int c宣言リストに追加する必要があります。

于 2013-08-25T01:49:21.053 に答える
3

デフォルトのパラメータは C の int 型で、K & R 構文についてはこちらこちらをご覧ください。

于 2013-08-24T18:29:40.380 に答える
3

C89 では、デフォルトの変数の型は、暗黙の intintとして定義されています。この規則は C99 で廃止されました。

あなたの例では、次のようにコンパイルされます。

main(int a,int b,int c,int d){printf("%d", d);}

foo(int a,int b){a=2; b='z';}
于 2013-08-24T18:27:03.990 に答える