

以下のようにStringのポインタアドレスを取得します

[code]

    var str = "test";
    var handle = GCHandle.Alloc(str, GCHandleType.Pinned);
    var ptr = handle.AddrOfPinnedObject();
    Console.WriteLine("0x{0}", ptr.ToString("x8"));
    
[/code]

このポインタ自体を置き換えるにはどうしたら良いのでしょうか？  
ポインタを書き換える という表現が正しいのかは分かりませんが、例えば

[code]

    static void Test(ref string str)
    {
        str = "changed";
    }
    
[/code]

このようなstringを参照として渡す関数を用意し、値を変更した場合  
書き換える前と後とでポインターアドレスが違います。  
この、ポインタを参照するポインタに新しいアドレスを設定したいのです。

正確なことは分かりませんが、私の推測ではC#のstring型には

  * 文字列の長さ情報を格納するアドレスを示すポインタ
  * 文字列の値情報を格納するアドレスを示すポインタ

が有り、AddrOfPinnedObjectが返すポインタは後者の

  * 文字列の値情報を格納するアドレスを示すポインタ

であると推測します。  
そこで、文字列の値情報を格納するアドレスを示すポインタのポインタを取得し、  
強引にポインタ自体を置き換える方法を探しています。

以上、よろしくお願いします。


CC BY-SA 3.0
2017-10-06T08:08:08.493
38486
2017-10-06T09:03:12.970
2017-10-06T08:17:51.157
24654
24654
question
c#
stringのポインターについて


.NET Frameworkの文字列型は連続したメモリ上で下記のようなフォーマットで記録されています。

  * 文字列長 (4バイト整数)
  * `char`配列 (2バイト×文字数)
  * NULL文字 (2バイト)

そして`string`のポインタは先頭の`char`を指しています。ですので元の文字数の範囲内で`((char*)ptr)[i]`に値を代入することで既存のインスタンスの表す値を書き換えることは可能ですが、ポインタへのポインタといったものは存在しないため再アロケーションが必要になる操作を行うことはできません。


CC BY-SA 3.0
2017-10-06T08:28:58.733
38488
2017-10-06T08:28:58.733
5750
38486
answer


> 文字列の値情報を格納するアドレスを示すポインタ

pgrhoさんの回答にもありますが、`String`オブジェクトは実体となる文字列を内包しているため、文字列へのポインタは保持していません。

> このポインタ自体を置き換えるにはどうしたら良いのでしょうか？

ポインタを保持していないため置き換えることはできません。また`String`オブジェクトはGCにより管理されているので、書き換えるべきでもありません。強引に書き換えた場合、次の例のように別の変数まで影響を受けることがあります。同一文字列であっても影響を受けない場合もあり、結果は予測不能と考えるべきです。

[code]

    var hoge1 = "hoge";
    var hoge2 = "hoge";
    unsafe
    {
        fixed(char* p = hoge1)
        {
            p[1] = 'a';
        }
    }
    Console.WriteLine($"{hoge1} and {hoge2}");
    // => hage and hage
    
[/code]


CC BY-SA 3.0
2017-10-06T09:03:12.970
38489
2017-10-06T09:03:12.970
4236
38486
answer