使用& # 39;固定# 39;用于指针语句

本文关键字:指针 语句 用于 固定 使用 | 更新日期: 2023-09-27 18:18:55

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

    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;
    }

我知道它只是把单元位置的四个字节放入字节数组,但我不清楚如何。

我的理解是:
(byte* pbyte = buff)

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

(uint*)pbyte

将pbyte的地址强制转换为int指针?

我不明白剩下的部分。固定的关键字有什么用?为什么不能这样做呢?

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

使用& # 39;固定# 39;用于指针语句

其他人已经解释了钉住的概念,但我认为让你困惑的是它都在一行。

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

等价于:

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

就像这样:

if(someCondition) DoSomething();

等价于:

if(someCondition)
{
    DoSomething();
}

明白了吗?现在应该很明显,第一部分是变量和相关块的声明,第二部分是赋值。

fixed语句防止垃圾回收器重新定位可移动变量。如果你省略它,你的地址可能会被改变,你会得到一个错误。

不能直接取数组的地址,因为它是由垃圾收集器管理的,这意味着它在内存中的位置随时都可能改变。fixed关键字将数组固定在其作用域的持续时间内,允许数组的四个字节由一个(4字节)的单位值填充。

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

例如,对象的引用对象B B和C,这意味着对象有一个指向对象的指针,C和对象也有一个指针指向对象A。然后,在推广阶段,地址的对象将从addr-old addr-new,然后,GC会修改指针的值对象的引用B和C对象修改后,对象B和C仍然有正确的指针,指向一个现在。

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

"fixed"语句将确保被管理对象"buff_buff_;"不会被提升。这也意味着它不会从这里移动到那里。