使用“固定”对于指针声明

发布于 2024-12-23 09:27:14 字数 619 浏览 3 评论 0原文

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

    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的地址转换为uint指针?

但我不明白其余的部分。 fixed 关键字有什么用?为什么不能这样做:

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

There's some code I'm reading and part of it is:

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

I understand that it's just putting the four bytes at the location of the unit into a byte array, but I'm not clear on how.

My understanding of it is that:

(byte* pbyte = buff)

creates and returns a byte pointer pbyte, which points to the address of buff,

(uint*)pbyte

Casts the address of pbyte into a uint pointer?

I don't understand the rest of it though. What's the use of the fixed keyword? Why can't it be done like:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

遗失的美好 2024-12-30 09:27:14

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

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

相当于:

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

就像这样:

if(someCondition) DoSomething();

相当于:

if(someCondition)
{
    DoSomething();
}

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

Others have explained the concept of pinning, but I think what has confused you is the fact that it is all on one line.

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

Is equivalent to:

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

Just as this:

if(someCondition) DoSomething();

Is equivalent to:

if(someCondition)
{
    DoSomething();
}

Does that clear it up? It should now be obvious that the first part is the declaration of the variable and the associated block, and the second part is the assignment.

神爱温柔 2024-12-30 09:27:14

fixed 语句可防止垃圾收集器重新定位可移动变量。如果您忽略它,您的地址可能会发生更改,并且您会收到错误消息。

The fixed statement prevents the garbage collector from relocating a movable variable. If you omit it, your address could get changed and you'll get an error.

水染的天色ゝ 2024-12-30 09:27:14

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

You can't just take the address of an array because it's managed by the garbage collector, meaning that its location in memory can change at any time. The fixed keyword pins the array in place for the duration of its scope, allowing the four bytes of the array to be filled by a (4-byte) uint value.

莫相离 2024-12-30 09:27:14

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地址是0x12345678)。现在,GC发生了,对象“buff”将被提升为新一代,这意味着对象“buff”将拥有新的内存地址,例如“0x55555555”。但是,“pbyte”是一个本机(非托管)对象,并且 CLR 不知道如何维护其生命周期,因此,虽然 pbytebuff 有关系,但是CLR无法将pbyte地址从0x12345678更改为0x55555555,指针“pbyte”仍然指向地址0x12345678,但该地址不属于对象“增益”;指针“pbyte”现在是一个坏指针。

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

During the CLR GC process, for normal GC heap objects (except LOH), the GC will mark and move the still alive objects to the next generation (this action also is named promoted). When promoting an object A, the GC will modify the object A address from addr-old to addr-new, and then update the relationships of all the objects who referenced to this objects.

For example, object A is referenced by object B and object C. This means object B have a pointer which is pointed to object A, and object C also have a pointer which is pointed to object A. Then, in the promoting phase, address of object A will be changed from addr-old to addr-new, then, GC will also modify the reference pointer value of object B and object C. After the modification, object B and C have the correct pointers which still pointed to A now.

After the line "byte* pbyte = buff" executed, pbyte has a pointer pointed to object "buff" , let's say the pbyte address is 0x12345678 (it also means buff address is 0x12345678). And now, GC happened, and the object "buff" will be promoted to a new generation, which means object "buff" will have a new memory address, for example, it's "0x55555555". But, "pbyte" is a native (unmanaged) object, and the CLR does not know how to maintain its lifecycle, so, although pbyte have a relationship with buff, but the CLR cannot change the pbyte address from 0x12345678 to 0x55555555, the pointer "pbyte" still points to address 0x12345678, but this address does not belong to object "buff"; the pointer "pbyte" is a bad pointer now.

The "fixed" statement will ensure the managed object "buff" will not be promoted. It also also means it will not be moved from here to there.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文