解释这个C#代码:byte * p =(byte *)(void *)Scan0;

时间:2009-10-30 02:42:19

标签: c# visual-studio-2008 pointers unsafe

我发现网上的代码我无法理解这一行: -

byte* p = (byte*)(void*)Scan0;

Scan0是 System.IntPtr。 它是C#.Net的代码。 Plz解释上述内容。

完整的代码如下。这是以灰度转换图像的代码。

public static Image GrayScale(Bitmap b)
    {

        BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

        int stride = bmData.Stride;
        System.IntPtr Scan0 = bmData.Scan0;

        unsafe
        {
            byte* p = (byte*)(void*)Scan0;

            int nOffset = stride - b.Width * 3;

            byte red, green, blue;

            for (int y = 0; y < b.Height; ++y)
            {
                for (int x = 0; x < b.Width; ++x)
                {
                    blue = p[0];
                    green = p[1];
                    red = p[2];

                    p[0] = p[1] = p[2] = (byte)(.299 * red + .587 * green + .114 * blue);

                    p += 3;
                }
                p += nOffset;
            }
        }

        b.UnlockBits(bmData);

        return (Image)b;
    }

我理解所有代码,但只有这一行有问题。

byte* p = (byte*)(void*)Scan0;

6 个答案:

答案 0 :(得分:5)

首先将IntPtr转换为void指针。然后到byte指针。这是unsafe代码。

有关不安全代码的更多信息: http://msdn.microsoft.com/en-us/library/aa288474%28VS.71%29.aspx

正如Robert Harvey所说,指针是一个记忆位置。在C / C ++中,数组与此概念密切相关。当它用方括号时,它基本上是调整地址。

答案 1 :(得分:4)

您的问题听起来好像在问代码正在做什么,但根据您的一些评论,我认为您是在为什么之后首先投放到无效指针。

你可能在这里感到困惑,因为没有理由首先将Scan0转换为void *。强制转换为byte *也可以正常工作。

答案 2 :(得分:2)

IntPtr有一个显式运算符(void *),允许转换为void *。如果你试图直接从IntPtr转换到其他东西,编译器会barf,因为只为IntPtr类定义了void * cast。另请参见IntPtr :: ToPointer()。

编译器允许从void *转换为byte *,因为此时如果您不知道自己在做什么,那么您已经遇到了麻烦。

答案 3 :(得分:1)

它看起来很奇怪,但后来我不太了解C#。 可能是将System.IntPtr直接投放到byte*而不是System.IntPtr投放到void*或{{1}的问题} void*

最终结果可能与在C中将byte*转换为int*时的结果相同:能够解除char*以获取整数的单个字节(假设CHAR_BIT为8)在C实现中。)

答案 4 :(得分:1)

查看有关不安全代码的本教程。它将解释代码行的含义,以及它如何用于除字节之外的其他类型:

http://msdn.microsoft.com/en-us/library/aa288474(VS.71).aspx

基本上,不安全的代码允许你使用c风格的指针。

答案 5 :(得分:0)

是否有可能需要强制转换为void以避免对象在其上执行某些自编代码?