C# 为什么字符串指针位置不同?

C# 为什么字符串指针位置不同?,c#,pointers,string-interning,unsafe-pointers,C#,Pointers,String Interning,Unsafe Pointers,为什么每次运行应用程序时,当我使用StringBuilder时,字符串指针的位置都不同,但在声明变量时,字符串指针的位置相同 void Main() { string str_01 = "my string"; string str_02 = GetString(); unsafe { fixed (char* pointerToStr_01 = str_01) { fixed (char* pointer

为什么每次运行应用程序时,当我使用
StringBuilder
时,字符串指针的位置都不同,但在声明变量时,字符串指针的位置相同

void Main()
{
    string str_01 = "my string";
    string str_02 = GetString();
    unsafe 
    {
        fixed (char* pointerToStr_01 = str_01)
        {
            fixed (char* pointerToStr_02 = str_02)
            {
                Console.WriteLine((Int64)pointerToStr_01);
                Console.WriteLine((Int64)pointerToStr_02);
            }
        }
    }
}

private string GetString()
{
    StringBuilder sb = new StringBuilder();
    sb.Append("my string");

    return sb.ToString();
}
输出:

40907812
178488268

下次:

40907812
179023248

下次:

40907812
178448964


str_01
保存对常量字符串的引用<但是,code>StringBuilder动态构建字符串实例,因此返回的字符串实例在引用上与具有相同内容的常量字符串不同
System.Object.ReferenceEquals()
将返回
false

由于
str_01
是对常量字符串的引用,因此它的数据可能存储在可执行文件的数据段中,该可执行文件在应用程序虚拟地址空间中始终获得相同的地址

编辑:

使用或类似软件打开编译的.exe文件时,可以看到UTF-8编码的“我的字符串”文本。它存在于文件的.data节中,包括一个首选虚拟地址,该节应加载到进程虚拟内存中


但是,我无法在应用程序的多次运行中重现
str_01
具有相同地址的情况,可能是因为我的x64 Windows 8.1执行了相同的操作。因此,在应用程序的多个运行中,所有指针都将不同,即使是直接指向加载的PE节的指针。

仅仅因为两个字符串相等,并不意味着它们指向相同的引用(我猜这意味着具有相同的指针),出于性能方面的考虑,C#不会自动对所有字符串进行内部搜索。如果您希望两个字符串的指针相同,可以使用
string.intern

stru 02
进行intern

 Console.WriteLine((Int64)pointerToStr_01);
这对你来说是一样的,因为我亲自测试了它,以使我的观点更清楚

让我们看看这两种情况:

  • 对于string str_01=“my string”,当您打印此变量的指针值时,它将与之前的不同,因为每次创建新的string对象(即string是不可变的)并为其指定“my string”。然后,在Fixed语句中,您正在打印指针的值,当您再次执行程序时,指针的值超出范围,以前的值将不会被记住
  • 我认为,到目前为止,您可以自行解释StringBuilder的行为
另外,请检查:

 string str_01 = GetString();
 private static string GetString()
    {
        var sb = new String(new char[] {'m','y',' ','s','t','r','i','n','g'});
        return sb;
    }

当我使用fixed时,它将分配内存
由于str_01是常量字符串,它在执行时分配内存,每次都指向相同的位置

fixed (char* pointerToStr_01 = str_01)
但是在

fixed (char* pointerToStr_02 = str_02)
它会动态分配内存,因此指针位置每次都会变化


因此,每次我们运行字符串指针时,字符串指针都会有所不同,为什么不呢?它们是不同的引用?@Selman22我明白了,但为什么
StringBuilder
字符串指针会发生变化,但我的varibale没有变化。没有真正的联系,但你究竟为什么要在C中使用指针?@Omada使用指针在C中非常好;跨
固定的
边界使用指向托管对象的指针(就像OP在这里所做的那样)几乎是不明智的。在任何语言中,期望在应用程序执行过程中变量的指针保持不变都是毫无意义的。我现在正在使用LINQPAD进行测试..第一个指针实际上每次都是相同的,这是有意义的,因为它是存储在可执行文件的字符串表中的字符串,因此,每次运行程序时,可能都会将其加载到相同的位置。