1

重複の可能性:
char *str=“STRING” と char str[] = “STRING” の違い?

次のコードを書きました。

int main()
{
    char *str = "hello";
    str[0] = 'H';
    printf("%s\n", str);
}

これにより、セグメンテーション違反が発生します。理由がわかりません。

strありpointer to charませんconst char。その場合でも、次のプログラムのようなコンパイル エラーが発生することはありません。

int main()
{
    const char *str = "hello";
    str[0] = 'H';
    printf("%s\n", str);    
}

エラーが発生します: assignment of read-only location *str

編集

私のコードが読み取り専用の場所へのポインターを配置した場合、コンパイル エラーが発生することはありませんか?

4

6 に答える 6

5

定数文字列 (テキストの一部として提供されるため、書き込み可能なメモリではありません) にポインターを割り当てます。

これを修正するとchar str[] = "hello";、スタックに定数文字列の a/w コピーが作成されます。

あなたがすることは、完全に有効なポインター割り当てです。コンパイラが認識していないのは、標準のシステム定数文字列が読み取り専用メモリに配置されていることです。組み込み (またはその他の奇妙な) システムでは、これは異なる場合があります。

mprotectシステムによっては、ポインターの宛先の VM フラグを書き込み可能に変更することができます。したがって、コンパイラはこのコードを許可しますが、OS は許可しません。

于 2012-10-06T17:11:10.717 に答える
2

リテラル文字列を使用して aを初期化する場合char *、その内容を変更しようとすべきではありません: 変数は、あなたに属していないメモリを指しています。

以下を使用できます。

char str[] = "hello";
str[0] = 'H';

このコードで、リテラル文字列の内容のコピーで初期化される配列を宣言したので、配列を変更できます。

于 2012-10-06T17:11:44.597 に答える
0

あなたのコードには、実行時の未定義の動作があります。許可されていないリテラル文字列に書き込もうとしています。このような書き込みは、エラーを引き起こしたり、未定義の動作をする可能性があります。特定の C コンパイラがstr読み取り専用メモリを指しており、そのメモリに書き込もうとするとセグメンテーション違反が発生します。ではありませんconstが、書き込みはまだ許可されていません。

于 2012-10-06T17:12:03.463 に答える
0
char *str = "hello";

上記のように宣言するstrと、メモリのどの部分に格納されるかは保証されません。str は、実装によっては読み取り専用になる場合があります。したがって、それを変更しようとすると、セグメンテーション違反が発生します。

セグメンテーション違反を避けるために、str代わりに文字の配列として宣言してください。

于 2012-10-06T17:12:20.743 に答える
0

str を char* として宣言すると、ポインタ用にメモリが予約されますが、文字列用には予約されません。コンパイラは、"hello" のメモリを好きな場所に置くことができます。str[i] が書き込み可能であるという保証はありません。そのため、一部のコンパイラでは、これにより seg fault が発生します。

文字列が書き込み可能なメモリにあることを確認したい場合は、 alloc() を使用してメモリを割り当てる必要があります。

char str[] = "hello";
于 2012-10-06T17:21:53.170 に答える
0
char *str = "hello";

ここで文字列 hello はリテラルです。文字列リテラルは常に読み取り専用メモリに格納されます。これが、読み取り専用メモリの値を変更しようとするとセグメンテーション違反が発生する理由です。

于 2012-10-06T17:13:09.627 に答える