不変の文字列値とポインタ アドレス
Go では、公式仕様では文字列は不変であると規定されており、文字列は作成後に変更できないことを意味します。 。ただし、次のコード スニペットから奇妙な観察が生じます:
str := "hello" fmt.Printf("%p\n",&str) // 0x1040c128 fmt.Printf("%v\n",str) // hello ptr := &str *ptr = "world" fmt.Printf("%p\n",&str) // 0x1040c128 fmt.Printf("%v\n",str) // world
予想に反して、「world」を逆参照ポインター *ptr に割り当てた後、&str のアドレスは変更されません。
この現象を理解するには、この文脈における「不変性」が何を意味するのかを理解する必要があります。 Go の文字列値は不変ですが、それを保持する変数は不変です。コード サンプルでは、str は文字列型の変数であり、その値は変更できます。
文字列値 "hello" 自体は不変です。 「world」を str に代入しても「hello」は変更されず、単に str 変数の値が「world」に変更されるだけです。この変更は、値の設定方法 (直接かポインタ経由か) には依存しません。
不変の文字列値により、プログラム全体で共有文字列の一貫性が保たれます。たとえば、関数が文字列引数を受け取った場合、その関数内でその値を変更することはできません。したがって、同じ文字列値の後続の print ステートメントは、常に予期した結果を生成します。
内部的に、文字列値は、reflect.StringHeader 構造体によって表されます。これらの構造体には、UTF-8 でエンコードされたテキストの値とそのバイト長へのポインターが格納されます。このデータにはアクセスできないため、直接変更できません。さらに、文字列値にインデックスを付けたり、新しい値を割り当てたりすることはできません。
Go 仕様では文字列値の不変性が保証されていますが、unsafe パッケージを使用するとこれらの保証が無効になる可能性があります。ただし、これを行うと、言語仕様によって提供される保護と安全性が放棄されます。
以上がGo でポインタを介して文字列の値を変更してもメモリ アドレスが変更されないのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。