我发现网上的代码我无法理解这一行: -
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;
答案 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
以避免对象在其上执行某些自编代码?