【问题标题】:Fixed pointer statement?固定指针语句?
【发布时间】:2011-12-29 02:25:47
【问题描述】:

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

    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;

【问题讨论】:

    标签: c# pointers fixed


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

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

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

      相当于:

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

      就像这样:

      if(someCondition) DoSomething();
      

      相当于:

      if(someCondition)
      {
          DoSomething();
      }
      

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

      【讨论】:

      • 谢谢,这样就搞定了。我认为声明是表达式的一部分..
      • @Walkerneo:老实说,它一开始也让我感到震惊,而且我(喜欢这样想)我非常精通 C#。我不得不看两次那条线,没有空格使它很丑。
      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        在 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”将有一个新的内存地址,例如,它是“0x55555555”。但是,“pbyte”是一个native(非托管)对象,CLR不知道如何维护它的生命周期,所以,虽然pbyte和buff有关系,但是CLR不能将pbyte地址从0x12345678更改为0x55555555。然后,指针“pbyte”仍然指向地址0x12345678,但是这个地址不属于对象“buff”,指针“pbyte”现在是一个坏指针。

        “固定”声明将确保被管理对象“buff”不会被提升,也意味着不会从这里移动到那里。

        【讨论】:

        • 太棒了,谢谢!这解释了固定关键字,但我仍然不明白该语句的逻辑。它如何将值的地址分配给 pbyte 指针?它是如何工作的?
        • 方法是GetBytes(uint value, bool BigEndian),第一个参数应该是一个uint值,是一个4字节的对象。因此,该方法先分配一个4字节的缓冲区,然后先将指针“pbyte”转换为uint*类型,然后将“值”分配给该类型为uint的地址。最后,该方法将“不安全”的缓冲区返回给其他不安全的方法使用。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-24
        • 2014-01-21
        • 2017-11-12
        • 1970-01-01
        相关资源
        最近更新 更多