Explique este código C #: byte * p = (byte *) (void *) Scan0;
-
22-07-2019 - |
Pregunta
Encontré el código de la red en el que no puedo entender esta línea: -
byte* p = (byte*)(void*)Scan0;
Allí Scan0 es System.IntPtr. Es el código de C # .Net. Por favor, explique la línea de arriba.
El código completo se proporciona a continuación. Este es el código para convertir una imagen en escala de grises.
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;
}
Entiendo todo el código pero solo tengo el problema en esta línea.
<*>Solución
Primero convierte el IntPtr
en un puntero void
. Luego a un puntero byte
. Este es el código inseguro
.
Más sobre código inseguro: http://msdn.microsoft.com/en-us /library/aa288474%28VS.71%29.aspx
Como señala Robert Harvey, un puntero es una ubicación de memoria. En C / C ++, las matrices están estrechamente relacionadas con este concepto. Cuando hace corchetes, básicamente está ajustando la dirección.
Otros consejos
Su pregunta suena como si estuviera preguntando qué está haciendo el código, pero en base a algunos de sus comentarios, creo que está buscando por qué está emitiendo primero a un puntero nulo.
Probablemente esté confundido aquí porque no hay razón para lanzar Scan0 primero a un vacío *. La conversión al byte * funcionaría igual de bien.
IntPtr tiene un operador explícito (void *) que permite convertir a void *. Si intenta transmitir directamente desde IntPtr a otra cosa, el compilador vomitará porque solo se define la conversión void * para la clase IntPtr. Vea también IntPtr :: ToPointer ().
El compilador permite la conversión de void * a byte * porque en este punto, si no sabe lo que está haciendo, ya está en problemas.
Parece extraño, pero entonces no conozco C # tan bien. puede ser que hay algún problema al enviar un System.IntPtr
directamente a un byte *
, pero no con System.IntPtr
a void *
o void *
a byte *
.
El resultado final es probablemente el mismo que si lanza int *
a char *
en C: la capacidad de quitar la defensa de p
para obtener un solo byte del entero (suponiendo que CHAR_BIT es 8 en la implementación de C).
Consulte este tutorial sobre código inseguro. Explicará qué significa la línea de código y cómo se puede usar para otros tipos además del byte:
http://msdn.microsoft.com/ es-es / library / aa288474 (VS.71) .aspx
Esencialmente, el código inseguro le permite usar punteros de estilo C.
¿Sería posible que necesite convertir a void
para evitar que el objeto ejecute algún código de auto-conversión en él?