使用& # 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;
其他人已经解释了钉住的概念,但我认为让你困惑的是它都在一行。
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不知道如何维护它的生命周期,所以,虽然pbyte与buff有关系,但是CLR不能将pbyte地址从0x12345678更改为0x55555555,指针"pbyte"仍然指向地址0x12345678,但是这个地址不属于对象buff";指针"是一个坏指针。
"fixed"语句将确保被管理对象"buff_buff_;"不会被提升。这也意味着它不会从这里移动到那里。