スタック、ヒープ、データ セグメント (および BSS)、およびテキスト セグメントは、プロセス メモリの 4 つのセグメントです。定義されたすべてのローカル変数はスタックになります。malloc と calloc を使用して動的に割り当てられたメモリはヒープになります。すべてのグローバル変数と静的変数はデータ セグメントになります。テキスト セグメントには、プログラムのアセンブリ コードといくつかの定数が含まれます。
これら 4 つのセグメントでは、テキスト セグメントは READ ONLY セグメントであり、他の 3 つのセグメントはすべて READ および WRITE 用です。
char []a="The redcoats are coming!";
- このステートメントは、スタックに 25 バイトのメモリを割り当て (ローカル変数のため)、最後に 24 文字すべてと NULL 文字 (\0) を保持します。
char *p="The redcoats are coming!";
- このステートメントは、スタック内の 4 バイト (32 ビット マシンの場合) のメモリを割り当て (これはローカル変数でもあるため)、値が "The redcoats are come!" である定数文字列のポインターを保持します。定数文字列のこのバイトは、テキスト セグメントになります。これは定数値です。ポインター変数 p は、その文字列を指すだけです。
Now a[0]
(index can be 0 to 24) は、スタックにあるその文字列の最初の文字にアクセスすることを意味します。したがって、この位置にも書き込むことができます。a[0] = 'x'
スタックに READ WRITE アクセス権があるため、この操作は許可されます。
しかしp[0] = 'x'
、テキスト セグメントへの読み取りアクセス権しかないため、クラッシュにつながります。テキストセグメントに書き込みを行うと、セグメンテーション違反が発生します。
ただし、スタック内のローカル変数であるため、変数 p の値を変更できます。以下のように
char *p = "string";
printf("%s", p);
p = "start";
printf("%s", p);
これは許可されています。ここでは、ポインタ変数 p に格納されているアドレスを文字列 start のアドレスに変更しています (ここでも start はテキスト セグメントの読み取り専用データです)。*p に存在する値を変更する場合は、動的に割り当てられたメモリを使用することを意味します。
char *p = NULL;
p = malloc(sizeof(char)*7);
strcpy(p, "string");
p[0] = 'x'
ヒープに書き込みを行っているため、操作が許可されます。