2
4

5 に答える 5

7

gets()どうやらそれが悪いことを除いて、私は使用できることを知っており、使用すべきではありません。

正確に、正確に - バッファ オーバーフロー エラーが発生する傾向があります。そしてscanf()、同じように悪です (部分的には同じ理由で - バッファ長を指定するのは簡単ではありません。とにかく、必要以上に複雑で、正しくするのは難しく、単純な生の I/O には非常に高価です)、donそれも使わない。ユーザー入力を取得するために使用fgets()します。書き込み先のバッファーの長さを渡せるようにすることで、足を撃たれるのを防ぎます。

char buf[0x40];
fgets(buf, sizeof(buf), stdin);

「方法」がわかったので、次に「理由」について説明します。

配列が関数に渡されると、ポインターに分解されると言われます。char []関数にa を渡すchar *と、配列の最初の要素を指す a として認識されます。&そのため、(char) 配列 (概念的には C の文字列) に対して "addressof" ( ) 演算子を明示的に使用する必要はありません。

それを使用すると、配列の最初の要素へのポインターは取得されませんが、配列自体へのポインターが取得されます。これは、必要なものではありません。

(一般的には、あなたの場合と同じように機能しますが、理論的には、渡された式の実際の型と変換指定子によって期待される型が一致しないため、未定義の動作が呼び出されます。)%s

このドキュメントは、配列とポインターに関する優れた読み物です。必ず読んで理解してください。

于 2013-07-06T06:43:44.630 に答える
2

配列を使用しています。配列への while 入力と&一緒に使用しないでくださいscanf

例えば:scanf("%s",first);

配列はすでに参照によって渡されています。&配列はCの最初の要素へのポインターとして既に渡されているため、配置する必要はありません

于 2013-07-06T06:34:46.337 に答える
1

scanfステートメントから & を削除します。

scanf("%s", first);  // first is pointer to start of first
scanf("%s", last);   // last is pointer to start of last 

C では、配列の名前は配列の先頭へのポインターです。

format パラメーターの後には、 1 つまたは複数のポインター引数scanfが必要です。

scanf(  "%s", first  );
scanf format-arg input-args

たとえば、整数パラメータが に使用されている場合scanf、& (アドレスを取得) 演算子が必要になります。

int n;
scanf("%d", &n);    // &n is pointer to n
于 2013-07-06T06:41:20.433 に答える
1

(および の類似性) に変更scanf("%s",&first);してみてください。scanf("%s",first);last

通常の状況 (これらを含む) では、配列の名前は配列内の最初の要素のアドレスに評価されます。この場合、これは char へのポインターでありscanf%s変換に必要な型です。

最初に を使用&すると、同じポインター(つまり、同じアドレス) が得られますが、配列の要素へのポインターではなく、配列へのポインターとして取得されます。これは が期待する型と一致しないため%s、結果は未定義の動作になります (ただし、これは正しいアドレスであるため、通常、これはほとんどの典型的なコンパイラ/CPU で機能します)。

于 2013-07-06T06:34:55.773 に答える
0

scanf にはアドレスが必要ですが、char 配列 [] は既にアドレスであり、名前自体がアドレスであるため、scanf には参照記号 & は必要ありません。

于 2013-07-06T06:36:48.093 に答える