このC#コードを説明してください:byte * p =(byte *)(void *)Scan0;
-
22-07-2019 - |
質問
この行を理解できないネットからコードを見つけました:-
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;
}
すべてのコードを理解していますが、この行に問題があるだけです。
<*>解決
まず、 IntPtr
を void
ポインターに変換します。次に、 byte
ポインターへ。これは unsafe
コードです。
安全でないコードの詳細: http://msdn.microsoft.com/en-us /library/aa288474%28VS.71%29.aspx
Robert Harveyが指摘しているように、ポインターはメモリの場所です。 C / C ++では、配列はこの概念と密接に結びついています。角括弧を使用する場合、基本的にアドレスを調整します。
他のヒント
あなたの質問は、コードが何をしているのか何を尋ねているように聞こえますが、いくつかのコメントに基づいて、なぜが最初にキャストしていると思います無効なポインター。
Scan0を最初にvoid *にキャストする理由がないため、ここで混乱する可能性があります。 byte *へのキャストも同様に機能します。
IntPtrには、void *へのキャストを許可する明示的な演算子(void *)があります。 IntPtrから他の何かに直接キャストしようとすると、IntPtrクラスに対してvoid *キャストのみが定義されているため、コンパイラーはbarfします。 IntPtr :: ToPointer()もご覧ください。
void *からbyte *へのキャストは、コンパイラーによって許可されています。なぜなら、この時点で何をしているのかわからない場合は、すでに問題になっているからです。
奇妙に見えますが、C#がよくわかりません。 System.IntPtr
を byte *
に直接キャストすることには問題があるかもしれませんが、 System.IntPtr
から void *
または void *
から byte *
へ。
最終結果は、おそらくCで int *
を char *
にキャストした場合と同じです: p
をデリファレンスして取得する機能整数の1バイト(C実装ではCHAR_BITが8であると仮定)。
安全でないコードに関するこのチュートリアルをご覧ください。コード行が何を意味するのか、そしてバイト以外の他のタイプでそれをどのように使用できるのかを説明します:
http://msdn.microsoft.com/ en-us / library / aa288474(VS.71).aspx
本質的に、安全でないコードではcスタイルのポインターを使用できます。
void
にキャストして、オブジェクトが自己キャストコードを実行しないようにする必要がある可能性はありますか?