だから私はCを始めたばかりで、この警告で何が起こっているのか問題があります。警告の意味と修正方法を教えてください。私が書いたコードはここにあります:
void main(void)
{
char* name = "";
int age = 0;
printf("input your name\n");
scanf("%s\n", name);
printf("input your age\n");
scanf("%d\n", age);
printf("%s %d\n", name, age);
}
scanf
関数は、結果を入れる変数のaddressを取ります。
書き込みscanf("%d", &someVar)
は、someVar
変数のaddressを渡します(_&
_単項演算子を使用)。scanf
関数は、そのアドレスのメモリの一部に数値をドロップします。 (これには変数が含まれます)
scanf("%d", age)
を記述するときは、age
変数のvalueをscanf
に渡します。 (age
は_0
_であるため)アドレス_0
_のメモリに数値をドロップしようとし、ひどくめちゃくちゃになります。
_&age
_をscanf
に渡す必要があります。
文字列をscanf
に読み込むには、name
にメモリを割り当てる必要もあります。
_char name[100];
scanf("%99s\n", name);
_
問題はこの行です:
scanf("%d\n", age);
scanfはポインター引数を期待します-これが関数がCのパラメーターを変更できる唯一の方法です。これを修正するには、次のことを行う必要があります。
scanf("%d\n", &age);
これは現在はポインタであるアドレスオブエージを渡します(ポインタは別のメモリ領域へのアドレスを含む変数です)。
これは:
char* name = "";
痛いのでお願いします!わかりました、私は説明する必要があります。あなたは文字タイプへのポインタを要求しましたが、誰もが知る限り、得られるのは文字列全体ではなく文字だけです。そうです、十分なスペースがありません。なぜCはこれを許可するのですか?まあ、Cは基本的に移植可能なアセンブラーなので、メモリ内の好きな場所に書き込むことができます(または、試してみるとコンパイラーが意見を異にすることはありませんが、オペレーティングシステムはそうすることができます)。
あなたがする必要があるのは、スペースを割り当てるためにmalloc
を使用してメモリ割り当てを読み取ることです。そうしないと、大量の文字列を入力して、それを名前のアドレス以降に置くことができます。
これは決してではありませんが、スタックベースの脆弱性につながる可能性があります。何、スタック?はい。スタックはFILO構造体であり、関数を呼び出すたびに、スタックに戻りアドレスと関数引数、および頻繁に関数スコープの変数用のスペースを追加します。
これが問題になるのは、入力サイズをチェックしない場合です。次に、実行可能コードを含む大量の値をスタックに書き込むことができます... バッファオーバーフロー を参照してください。
では、どうすればこれを緩和できると思いますか。ソフトウェアの脆弱性を実装しないことを切望しています。バッファーの入力サイズを指定して特定のサイズのバッファーに読み込み、そこから移動できる関数を使用します。それでおしまい。とても簡単です。
次の質問を参照してください: Cでの文字列の読み取り 。
scanf
関数はmodifyage
の値を必要とするため、scanf("%d", &age)
を記述する必要があるため、「アドレスで」渡す必要があります。 「値渡し」ではありません。
これは、 "int *"(つまり、整数へのポインタ)を期待していることを意味しますが、整数である "int"を指定します。それを修正するには、scanf行に&を追加して年齢になるようにします。
scanf( "%d\n"、年齢);
行scanf("%d\n", age);
に関する不満を想定しています。問題は、スキャンfが変数ではなく変数へのポインターを期待していることです。 '& `を付加して変数へのアドレスを取得する必要があり、問題ありません。
警告は正確にそれが言うことを意味します:コンパイラはint
呼び出しでint
ではなくscanf
へのポインタを期待します。
クイックフィックス:age
を&age
に置き換えると、すべてが機能します。
Cはすべての引数を値で渡します。つまり、変数を渡す場合、変数の値のみが渡されます。受信側の関数は、必要なすべての値を変更できますが、元の値は変更されません。変数を変更するには、変数を指す値をなんらかの方法で渡す必要があります。これはCではポインタです。
変数へのポインタを取得するには、変数の前に&
を付けます。ポインタのある変数を使用するには、ポインタ値の前に*
を付けます。
この場合、scanf
がage
の値を変更するようにしたいので、それにポインターを渡す必要があります。
_char* name = "";
_
name
は、単一のヌル文字を保持するのに十分な大きさのビットまたはメモリを指します。
_scanf("%s\n", name);
_
不明な数の文字を読み取り、このアドレスに格納するように要求します。 すべてが発生する可能性があります。あなたは必須name
がメモリを保持するのに十分な大きさのメモリのチャンクのアドレスを持っていることを確認しますanythingscanf()
が読み取る可能性があります。
_char twenty_bytes[20] = "";
scanf("%s\n", twenty_bytes);
_