4
int main(void)
{
    char name1[5];
    int count;
    printf("Please enter names\n");
    count = scanf("%s",name1);
    printf("You entered name1 %s\n",name1);
    return 0;
}

5文字を超えて入力すると、入力したとおりに文字が出力され、5文字を超えていましたが、char配列は次のように宣言されています。

char name1[5];

どうしてこうなった

4

6 に答える 6

12

文字は「ストレージスペース」の後のアドレスに保存されるためです。これは非常に危険であり、クラッシュにつながる可能性があります。

たとえば、name: Michael と入力し、name1 変数が 0x1000 から始まるとします。

name1: M       i     c      h      a      e      l     \0
      0x1000 0x1001 0x1002 0x1003 0x1004 0x1005 0x1006 0x1007
      [................................]

割り当てられたスペースは [...] で示されます。これは、メモリが 0x1005 から上書きされることを意味します。

解決:

5 文字 (末尾の \0 を含む) のみをコピーするか、入力した文字列の長さを確認してからコピーしてください。

于 2013-07-15T14:57:24.080 に答える
6

これは未定義の動作です。割り当てられたメモリの範囲を超えて書き込んでいます。正常に動作しているように見えるプログラムを含め、あらゆることが起こる可能性があります。

C99 ドラフト標準セクションのJ.2 Undefined Behaviorには、次のように記載されています。

次の状況では、動作は未定義です。

次の箇条書きが含まれています。

オブジェクトが与えられた添え字で明らかにアクセス可能であっても (int a[4][5] 宣言が与えられた左辺値式 a[1][7] のように)、配列添え字は範囲外です (6.5.6)。

E1[E2] は (*((E1)+(E2))) と同一であるため、これはより一般的なケースに適用されます。

于 2013-07-15T14:59:46.757 に答える
2

これは未定義の動作であり、当てにすることはできません。たまたま機能するだけで、別のマシンでは機能しない可能性があります。

バッファ オーバーフローを回避するには、次を使用します。

fgets(name1, sizeof(name1) - 1, stdin);

またはC11で

gets_s(name1, sizeof(name1) - 1);
于 2013-07-15T14:59:57.543 に答える
2

物事を明確にする別の例:

 #include <stdio.h> 

 int array[5] ;

 int main ( void )
 {

  array[-1] = array[-1] ; // sound strange ??

  printf ( "%d" , array[-1] ) ; // but work !!
  return 0 ;
 }

この場合、配列はアドレス内にあり、そのアドレスの前後に数値を取得しますが、何をすべきかを理解していない限り、これは未定義の動作です。ポインタは ++ または -- で動作します!

于 2013-07-15T16:11:12.850 に答える