Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/285.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 固定指针语句?_C#_Pointers_Fixed - Fatal编程技术网

C# 固定指针语句?

C# 固定指针语句?,c#,pointers,fixed,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();

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

    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;

fixed语句防止垃圾收集器重新定位可移动变量。如果省略它,您的地址可能会更改,并且会出现错误。您不能只获取数组的地址,因为它是由垃圾收集器管理的,这意味着它在内存中的位置可以随时更改。fixed关键字在其作用域的持续时间内将数组固定到位,允许数组的四个字节由(4字节)uint值填充。

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

例如,对象A被对象B和对象C引用,这意味着对象B有一个指向对象A的指针,对象C也有一个指向对象A的指针。然后,在升级阶段,对象A的地址将从addr old更改为addr new,然后,GC还将修改对象B和对象C的参考指针值。修改后,对象B和对象C具有正确的指针,现在仍然指向A

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


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

其他人已经解释了钉扎的概念,但我认为让你困惑的是,它都在一条线上

fixed (byte* pbyte = buff)*((uint*)pbyte) = value;
相当于:

fixed (byte* pbyte = buff)
{
    *((uint*)pbyte) = value;
}
if(someCondition)
{
    DoSomething();
}
正如此:

if(someCondition) DoSomething();
相当于:

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

这就清楚了吗?现在应该很明显,第一部分是变量和关联块的声明,第二部分是赋值。

太棒了,谢谢!这就解释了fixed关键字,但我仍然不理解该语句的逻辑。如何将值的地址分配给pbyte指针?它是如何工作的?方法是GetBytes(uint值,bool BigEndian),第一个参数应该是uint值,它是一个4字节的对象。因此,该方法首先分配一个4字节的缓冲区,然后首先将指针“pbyte”强制转换为uint*类型,然后将“value”分配给该地址,该地址的类型是uint。最后,此方法将“不安全”缓冲区返回给其他不安全的方法使用。谢谢,这将清除它。我认为声明是表达的一部分。@Walkereno:老实说,一开始它也让我感到震惊,我(喜欢这样认为)我对C#非常精通。我不得不看了两遍那条线,因为没有空间,所以很难看。