2010-03-11 23 views
5

esos 3 tipos son muy similares ...tarray <Byte> VS VS TBytes PByteArray

tarray es la versión genérica de Tbytes. Ambos se pueden convertir a PByteArray y se utilizan como búfer para las llamadas a la API de Windows. (con las mismas restricciones que la cadena a Pchar).

Lo que me gustaría saber: este comportamiento es "por diseño" o "Por implementación". O más específicamente, ¿podría romperse en futuras versiones?

// Editar Como se indica más abajo ... Lo que realmente quiero saber es: ¿Esto es lo más seguro para encasillado Tbytes (o tarray) a PByteArray como lo es para encasillado cadena a PChar por lo que la compatibilidad hacia adelante es preocupado. (O tal vez AnsiString para PAnsiChar es un mejor ejemplo^_ ^)

Respuesta

3

En pocas palabras, una matriz de bytes es una matriz de bytes, y mientras las definiciones de un byte y una matriz no cambien, este won tampoco cambias Puede usarlo de forma segura, siempre y cuando se asegure de respetar los límites de la matriz, ya que expulsarlo de los tipos de matriz de Delphi anula la verificación de límites.

EDIT: Creo que veo lo que estás preguntando un poco mejor ahora.

No, no debe lanzar una referencia de matriz dinámica a un puntero de matriz de estilo C. Puede salirse con la suya con cuerdas porque el compilador lo ayuda un poco.

Lo que puede hacer, sin embargo, es convertir un puntero al elemento 0 de la matriz dinámica en un puntero de matriz de estilo C. Que funcionará, y no cambiará.

+0

En realidad, está equivocado ... una "Matriz de byte" no es una matriz de bytes ... Es un puntero a una matriz dinámica de bytes que es referencia contada y longitud manejada (casi como cadenas). Lo que quiero saber es: ¿Esto es tan seguro para el tipo TBytes (o TArray ) a PByteArray como para encasillar Cadena a PChar en lo que concierne a la compatibilidad con versiones anteriores? –

+0

Una "matriz de bytes" ** es ** una matriz de bytes. La única diferencia es que se muestra al entorno de ejecución principalmente como * tipo de referencia *, en lugar de * tipo de valor * (como en el caso de una matriz estática). El compilador lo sabe, por supuesto, y (de acuerdo, debería) encargarse del encasillado para usted de la misma manera que lo hace con String <> PChar (a menudo denominado "compilación mágica", es decir, generación de código que depende del compilador). siendo consciente de sus propios internos). – Deltics

+0

@Ken: Bien, entiendo a qué te refieres. Editando mi respuesta –

1

Dos de esos tipos son similares (idénticos de hecho). El tercero no es.

tarray se declara como "Matriz de Byte", como es TBytes. Sin embargo, omitió otro tipo muy relevante, TByteArray (el tipo al que hace referencia PByteArray).

ser un puntero a TByteArray, PByteArray es estrictamente hablando un puntero a una matriz de bytes estática, no una matriz dinámica (que los otros tipos de matrices de bytes son todos). Se escribe de esta manera para permitir la referencia a las compensaciones de ese puntero base usando un índice entero. Y tenga en cuenta que esta indexación está limitada a 2^15 elementos (0..32767). Para desplazamientos arbitrarios de bytes (> 32767) de algunos puntero base, un PByteArray no es bueno:

var 
    b: Byte; 
    ab: TArray<Byte>; 
    pba: PByteArray; 
begin 
    SetLength(ab, 100000); 
    pba := @ab;    // << No cast necessary - the compiler knows (magic!) 
    b := pba[62767];  // << COMPILE ERROR! 
end; 

es decir, que emiten un Matriz de Byte o una tarray a un PByteArray es potencialmente va a llevar a problemas donde la matriz tiene> 32K elementos (y el puntero se pasa a un código que intenta acceder a todos los elementos). Casting a un puntero sin tipo lo evita por supuesto (siempre que el "destinatario" del puntero maneje el acceso a la referencia de memoria por el puntero apropiadamente).

PERO, nada de esto es probable que cambie en el futuro, es simplemente una consecuencia de los detalles de implementación que desde hace tiempo se aplican en esta área.La introducción de una declaración de tipo genérica azucarada sintácticamente es kipper rouge.

+0

Por un lado no, si es necesario, el límite 32767 se puede anular redeclarando localmente el tipo de esta manera. tipo PByteArray =^TByteArray; TByteArray = array [0..MaxInt - 1] de Byte; –

+0

"Kipper rouge"? Qué significa eso? –

+0

Lo siento - Kipper Rouge = "Red Herring" :) – Deltics