unsafe static void Main(string[] args)
{
int i=6;
int* j = &i; //Allowed
int* k = j; //Allowed
fixed(int* q = &i) //Allowed
{
}
fixed(int* q = j) //Cannot declare pointer to non unmanaged type int*
{
}
}
我在使用第二个固定块时所做的与第一个固定块的操作非常相似。 我将变量i的地址分配给指针q。允许直接地址分配,而在另一个指针中取地址并在赋值中使用该指针失败。然而,相同的步骤在固定的上下文之外工作..发生了什么?!
答案 0 :(得分:0)
您使用的是哪个版本的C#?第一个fixed
语句也没有为我编译(You cannot use the fixed statement to take the address of an already fixed expression
)。
修复非托管指针没有意义。它已经修复,GC无法触及它。
例如,当您将i
作为类的成员字段时,这会发生变化。突然间,它不再作用于方法,并且可以移动GC(以及它的计数对象)。在这种情况下,您有使用fixed
语句。
编译器不允许您获取指向未固定的托管变量的指针,并且它不允许您修复非托管或固定变量。
同样的方法,如果你把一个指针指向一个数组的开头,例如。 make int[] i
并取&i[0]
,它又需要修复,因为它不再保证是本地范围的。如果确实需要本地作用域的非托管数组,则可以使用stackalloc
关键字,但这又基本上意味着您将自己从托管.NET的相对安全性中解脱出来。
答案 1 :(得分:0)
The fixed
statement用于 pin 一个托管变量,因此垃圾收集器不会移动它。
在正常操作中,垃圾收集器可以自由移动对象。这对于指针来说是一个问题,因为如果垃圾收集器移动了一个指针指向的对象,则指针将不再有效。 fixed
通过让 pin 变量来提供解决方案,告诉垃圾收集器指向该对象的指针可能存在,并且它不能在代码块的持续时间内移动它们。
C#编译器只允许您在固定语句中为托管变量分配指针。
在堆栈上分配的变量(值类型)不受垃圾回收器的限制,也不会在内存中移动,因此fixed
对于这些变量来说既不必要又不正确。这就是你的第二个(实际上是你的第一个)fixed
语句产生错误的原因。