我目前正在大学攻读计算机科学课程,我们最近看到了如何使用&amp ;;来获取变量的内存地址。和*在调试器中。我的老师告诉我,本地值类型变量在堆栈中,引用类型在堆中。但他也告诉堆栈应该包含字符串在堆中的地址。
我不知道你是否明白我想说的是什么,但它应该是可能的,因为我在他给我们的笔记中看到了它。但当他试图向我们展示时,它没有用,他不知道为什么。
我想知道怎么做,但是当我尝试时,我总是收到此错误消息:
不能获取地址,获取大小,或声明指向托管类型('string')的指针。
我在调试器中没有引号写&nameofstringvariable
。我想了解事情是如何运作的,我在谷歌搜索这个问题的时间,但我从来没有找到解决方案。尝试使用unsafe
代码并且无效。
答案 0 :(得分:14)
我目前正在大学攻读计算机科学课程,我们最近看到了如何使用&amp ;;来获取变量的内存地址。和*在调试器中
&
为您提供C#中非托管类型的固定变量的地址;结果是一个指针。 *
取消引用指针并将其转回变量,它不会为您提供变量的地址。
我的老师告诉我,本地值类型变量在堆栈中,引用类型在堆中。
让我们确保我们做对了,因为这非常令人困惑。
如果已知其生命周期为,则局部变量将在堆栈上运行,无论该变量是包含值类型的实例还是对堆的引用。请注意,局部变量的生命周期不需要很短!考虑例如λ的封闭外部变量;它的生命周期与关联的委托相同,并且不会很短,所以它不能进入堆栈。
引用类型的实例在堆上,因此与引用类型实例关联的变量在堆上。但引用不一定是。参考类型和参考类型的实例与蛋糕和烹饪书籍不同。
他还告诉堆栈应该包含字符串在堆中的地址。
正确;如果有一个短期变量或值,它是对堆上字符串的引用,那么该变量或值将存储在堆栈中。请注意,这是一个托管引用,而不是非托管引用。
但是当他试图向我们展示时,它没有用,他不知道为什么。
也许他应该是那时问这个问题的人。
我想知道怎么做,但是当我尝试时,我总是收到此错误消息:
正确。您不能像这样操纵托管引用。
我在调试器中没有引号写
&nameofstringvariable
它为您提供包含引用的变量的地址。它没有给你参考!
看,你有一张纸上写着“123芝麻街”。这是一个房子的参考。你把那张纸放在宾夕法尼亚大道1600号。当你要求提供这张纸的地址时,它位于宾夕法尼亚大道1600号,而不是123芝麻街。
无论如何,获取托管类型变量的地址是不合法的。
我想了解事情是如何运作的,我在google上搜索了这个问题,但我从来没有找到解决方案
您应该阅读C#规范的第18章。小心。
你还应该阅读我关于这个主题的所有文章,并让你的老师在你的时候阅读它们。
http://blogs.msdn.com/b/ericlippert/archive/2009/02/17/references-are-not-addresses.aspx
http://blogs.msdn.com/b/ericlippert/archive/2009/04/27/the-stack-is-an-implementation-detail.aspx
http://blogs.msdn.com/b/ericlippert/archive/2010/09/30/the-truth-about-value-types.aspx
http://blogs.msdn.com/b/ericlippert/archive/2010/10/11/debunking-another-myth-about-value-types.aspx
所以现在有些问题没有问:
所以不可能将字符串的托管引用作为指针获取?
是。 <#>在C#语言中不可能将托管引用作为指针。
但我能做到这一点!
string str = "Hello World";
fixed (char* p = str) { /*...*/ }
现在我有一个指向字符串中第一个字符的指针。这不是一回事吗?
当然不是!这是指向char
的非托管指针,而不是指向string
的托管指针。面包盒中第一片面包的位置与面包盒的位置不同。
调试器是否可以获取与字符串关联的托管地址?
不确定。查看内存窗口中的堆栈帧;其中一些值将是托管地址。