固定指针语句?

时间:2011-12-29 02:25:47

标签: c# pointers fixed

我正在阅读一些代码,其中一部分是:

    public static unsafe byte[] GetBytes(uint value, bool BigEndian)
    {
        byte[] buff = new byte[4];
        fixed (byte* pbyte = buff)*((uint*)pbyte) = value;
        if (BigEndian)
            buff.EndianConvert();
        return buff;
    }

我知道它只是将单元位置的4个字节放入一个字节数组,但我不知道如何。

我对它的理解是:

(byte* pbyte = buff)

创建并返回一个字节指针pbyte,它指向buff的地址,

(uint*)pbyte

将pbyte的地址转换为uint指针?,

我不了解其余部分。固定关键字有什么用?为什么不能这样做:

(byte* pbyte = buff) = (byte*)value;

4 个答案:

答案 0 :(得分:2)

fixed语句阻止垃圾收集器重定位可移动变量。如果你省略它,你的地址可能会改变,你会收到错误

答案 1 :(得分:1)

您不能只获取数组的地址,因为它由垃圾收集器管理,这意味着它在内存中的位置可以随时更改。固定关键字将数组固定在其范围的持续时间内,允许数组的四个字节由(4字节)uint值填充。

答案 2 :(得分:1)

其他人已经解释了固定的概念,但我认为令你感到困惑的事实是,这一切都在一条线上。

fixed (byte* pbyte = buff)*((uint*)pbyte) = value;

相当于:

fixed (byte* pbyte = buff)
{
    *((uint*)pbyte) = value;
}

就像这样:

if(someCondition) DoSomething();

相当于:

if(someCondition)
{
    DoSomething();
}

那清除了吗?现在显而易见的是,第一部分是变量和相关块的声明,第二部分是赋值。

答案 3 :(得分:0)

在CLR GC过程中,对于普通的GC堆对象(LOH除外),GC会将仍然存活的对象标记并移动到下一代(此操作也命名为promote)。在提升对象A时,GC会将对象A地址从addr-old修改为addr-new,然后更新引用此对象的所有对象的关系。

例如,对象A由对象B和对象C引用,这意味着对象B具有指向对象A的指针,对象C也具有指向对象A的指针。然后,在促销中阶段,对象A的地址将从addr-old更改为addr-new,然后,GC还将修改对象B和对象C的引用指针值。修改后,对象B和C具有仍然指向的正确指针到了现在。

在执行“byte * pbyte = buff”行之后,pbyte有一个指向对象“buff”的指针,假设pbyte地址是0x12345678(也就是说buff addr是0x12345678)。现在,GC发生了,对象“buff”将被提升为新一代,这意味着对象“buff”将有一个新的内存地址,例如,它是“0x55555555”。但是,“pbyte”是一个本机(非托管)对象,CLR不知道如何维护它的'生命周期,所以,尽管pbyte与buff有关系,但CLR无法将pbyte地址从0x12345678更改为0x55555555。然后,指针“pbyte”仍然指向地址0x12345678,但是这个地址不属于对象“buff”,指针“pbyte”现在是一个坏指针。

“fixed”语句将确保托管对象“buff”不会被提升,也意味着不会从这里移动到那里。