0

のフォーマット指定子文字列で使用されるフォーマット指定子char*の唯一の有効な引数タイプではありませんか?もしそうなら、私のプログラムでは、これらのそれぞれが と の両方の %s フォーマット指定子に対してまったく同じように機能するのはなぜですか?%sscanf()scanf()printf()

scanf("%s",&list[i]);
scanf("%s",list[i]);   
scanf("%s",&list[i][0]);

この前提から生じる次の混乱を解消していただければ幸いです。

1)&name[i]タイプであるchar (*)[]のに、なぜ機能&name[i][0]するのですchar*か?

2)の引数として渡すと、name[i]分解/変換されますか?入力した各名前の最初の文字のアドレスであるを渡すのと同じですか?なぜそれが機能するのですか?char*%s&name[i][0]

#include<stdio.h>
#include<string.h>

int main(void)
{

char list[3][10];
int i;
printf("Enter the three names \n");

for(i=0;i<=2;i++)
scanf("%s",&list[i]);  //Why this works?
//scanf("%s",list[i]);   //Does it decompose into char* type?
//scanf("%s",&list[i][0]);

for(i=0;i<=2;i++)
printf("%s\n",list+i);  //All of these printf() work as well
//printf("%s\n",list[i]);
//printf("%s\n",&list[i][0]);

}
4

3 に答える 3

3

list[i]は でありchar[10]、引数として渡されると配列からポインターへの変換が行われるため、その場所では と完全に同等&list[i][0]です。

&list[i]は、またはの変換指定子char(*)[10]の無効な引数であり、未定義の動作を引き起こします。%sprintfscanf

ただし、 の最初のバイトlist[i]は array と同じアドレスを持つためlist[i]、通常は(1)で動作します。これは、printfscanfが引数の型を認識せず、書式文字列に従って解釈するためです。

(1) a の表現a の表現とchar*異なる場合、失敗しchar(*)[10]ます。それは珍しいことですが、可能です。

于 2013-05-13T14:09:07.333 に答える
2

可変引数リスト ( printf()orに使用されるようなものscanf())は、可変引数の型の正確性をチェックできません。反対に、これらの関数は正しいタイプを示すフォーマット文字列に依存します。これは、フォーマット文字列がスタックから引き出される引数の数とタイプを定義するためです。

<stdargs.h>(可変引数リストがどのように機能するかの詳細については、ドキュメントを確認してください。)

"%s"フォーマット指定子として指定すると、実際にパラメーターとしてを指定したか、またはパラメーターを指定したかどうかに関係なく、スタックからscanf()achar *を取得し、標準入力をそのアドレスに書き込みます。

言うまでもなく、フォーマット指定子が引数の数、型、および順序と一致しない場合、幸運で実際に結果が得られる可能性がありますが、未定義の動作を呼び出していることは間違いありません。

(これは、GCCのように最新のコンパイラがなく、適切な警告が有効になっていると仮定して、「なぜこれでエラーが発生しないのか」という一般的な質問について話しています。特定のケースで-Wformatの型変換については、ダニエルの答えを見てください。)


追伸:scanf()現在のところ、 with を組み合わせて使用​​することは%s、いずれにせよ非常に致命的です。入力が長すぎると、プログラムが壊れてしまうからです。少なくとも入力を制限して%10sください。さらに良いことに、入力を経由で読み取り、メモリ内で適切な入力解析をfgets()行います。不正な形式の入力から正常に回復する の能力は非常に限られているためです。scanf()

于 2013-05-13T14:07:45.023 に答える