2009-10-30 25 views
1

我發現從網上的代碼中,我無法理解這行: -說明這個C#代碼:byte * p =(byte *)(void *)Scan0;

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; 
+10

它恰好拼寫爲「please」。 – 2009-10-30 03:10:00

回答

5

首先IntPtr轉換爲void指針。然後到一個byte指針。這是unsafe的代碼。

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

正如羅伯特·哈維指出,一個指針是一個內存位置。在C/C++中,數組與這個概念密切相關。當它做方括號時,它基本上是調整地址。

+0

謝謝先生,我理解指針和不安全代碼的概念。你能否給出一些關於void指針的更多解釋。 – qulzam 2009-10-30 02:57:43

+3

無效指針以非常基本的方式是指向無特定類型的指針。所以,你得到一個指向不引用任何類型的地址的指針,簡單地說就是該地址的數據。然後,你可以自由地將它投射到任何你喜歡的地方。在這個例子中,他們把一個Int賦給一個void(沒有)。 void指針(原始內存地址)然後被轉換爲一個字節的地址。 (好主人,這是我從事此工作以來一直存在的,有人請糾正我,如果我錯了)。 – 2009-10-30 03:05:57

1

它看起來奇怪,但我不知道C#那麼好。它可能是有一些問題,直接鑄造System.IntPtrbyte*,但不能與System.IntPtrvoid*void*byte*

最終的結果可能是一樣的,如果你用C投int*char*:能夠反引用p得到整數的單字節(假設CHAR_BIT是8 C實現)。

1

查看關於不安全代碼的教程。這將解釋什麼的代碼行手段,以及如何將它用於其他類型的除了字節:

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

從本質上講,不安全的代碼,允許你使用C風格的指針。

+0

我明白不安全的代碼,但是有一些混淆(byte *)(void *)的含義是什麼, – qulzam 2009-10-30 03:03:07

4

你的問題聽起來就好像你問什麼代碼是幹什麼的,但基於一些您的意見,我認爲你是它的第一投射到一個空指針爲什麼後。

您可能會對此感到困惑,因爲沒有理由先將Scan0投射到void *。轉換爲字節*也可以。

0

有沒有可能,你需要轉換爲void,以避免它執行一些自投代碼的對象?

2

IntPtr有一個顯式操作符(void *),它允許強制轉換爲void *。如果你試圖直接從IntPtr轉換到別的東西,那麼編譯器會禁用,因爲只有void * cast被定義爲IntPtr類。另請參閱IntPtr :: ToPointer()。

從void *的爲字節*鑄造是由編譯器,因爲此時允許,如果你不知道你在做什麼,你就麻煩了。