开发者

Explain this C# code: byte* p = (byte*) (void*) Scan0;

开发者 https://www.devze.com 2022-12-10 15:20 出处:网络
I found the code from the net in which i cant understand this line:- byte* p = (byte*)(void*)Scan0; There Scan0 is System.IntPtr.

I found the code from the net in which i cant understand this line:-

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

There Scan0 is System.IntPtr. It is code of C#.Net. Plz Explain the above line.

The complete code is given below. this is code to convert a image in grayscale.

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

I understand all the code but only have the problem on this line.

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


First converts the IntPtr to a void pointer. Then to a byte pointer. This is unsafe code.

More on unsafe code: http://msdn.microsoft.com/en-us/library/aa288474%28VS.71%29.aspx

As Robert Harvey notes, a pointer is a memory location. In C/C++ arrays are closely tied to this concept. When it does the square brackets, its basically is adjusting the address.


Your question sounds as if you are asking what the code is doing, but based on some of your comments I think you are after why it is casting first to a void pointer.

You are likely confused here because there is no reason to be casting Scan0 first to a void*. The cast to byte* would work just as well.


IntPtr has an explicit operator (void*) that allows casting to void*. If you try to cast directly from IntPtr to something else the compiler will barf because only the void* cast is defined for the IntPtr class. See also IntPtr::ToPointer( ).

Casting from void* to byte* is allowed by the compiler because at this point if you don't know what you're doing you're already in trouble.


It looks bizarre but then I don't know C# that well. It may be that there's some problem with casting a System.IntPtr directly to a byte*, but not with System.IntPtr to void* or void* to byte*.

The end result is probably the same as if you cast int* to char* in C: the ability to derefence p to get a single byte of the integer (assuming CHAR_BIT is 8 in the C implementation).


Check out this tutorial on unsafe code. It will explain what the line of code means, and how it can be used for other types besides byte:

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

Essentially, unsafe code allows you to use c-style pointers.


Would it be possible that you need to cast to void to avoid the object from executing some self-cast code on it?

0

精彩评论

暂无评论...
验证码 换一张
取 消