无法将指针声明为非非托管类型int * C#

时间:2014-03-04 15:01:41

标签: c# pointers unmanaged fixed managed

  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。允许直接地址分配,而在另一个指针中取地址并在赋值中使用该指针失败。然而,相同的步骤在固定的上下文之外工作..发生了什么?!

2 个答案:

答案 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语句产生错误的原因。