2010-03-11 11 views
5

Questi 3 tipi sono molto simili ...tarray <Byte> VS Tbyte VS PByteArray

tarray è la versione generica di Tbyte. Entrambi possono essere convertiti in PByteArray e utilizzati come buffer per le chiamate all'API di Windows. (con le stesse restrizioni della stringa a Pchar).

Che cosa vorrei sapere: questo comportamento è "di progettazione" o "di implementazione". O più specificamente, potrebbe rompere in una versione futura?

// Modifica Come dichiarato più basso ... Quello che voglio davvero sapere è: E 'questo come sicuro da typecast Tbyte (o tarray) per PByteArray quanto lo è per typecast Stringa da PChar quanto riguarda la compatibilità in avanti è ha riguardato. (O forse AnsiString to PAnsiChar è un esempio migliore^_ ^)

risposta

3

In poche parole, una matrice di byte è una matrice di byte, e fintanto che le definizioni di un byte e di un array non cambiano, questo ha vinto cambiano entrambi. Si è sicuri di usarlo in questo modo, purché si assicuri di rispettare i limiti dell'array, dal momento che lanciarlo dai tipi di array di Delphi annulla il controllo dei limiti.

EDIT: Penso di vedere cosa stai chiedendo un po 'meglio ora.

No, non si deve eseguire il cast di un riferimento di array dinamico a un puntatore di matrice in stile C. Puoi farla franca con le stringhe perché il compilatore ti aiuta un po '.

Ciò che si può fare, tuttavia, è lanciare un puntatore all'elemento 0 dell'array dinamico su un puntatore di matrice in stile C. Che sarà funzionerà e non cambierà.

+0

In realtà, si sbaglia ... una "matrice di byte" non è una matrice di byte ... È un puntatore a una matrice dinamica di byte che è conteggiata con riferimento e con lunghezza gestita (simile alle stringhe). Quello che voglio sapere è: è sicuro digitare TByte (o TArray ) in PByteArray così come è stato convertito da String a PChar per quanto riguarda la compatibilità diretta. –

+0

Una "matrice di byte" ** è ** una matrice di byte. L'unica differenza è che viene riportato al runtime principalmente come un * tipo di riferimento *, piuttosto che un * tipo di valore * (come nel caso di un array statico). Il compilatore lo sa e ovviamente (ok, dovrebbe) si prenderà cura di typecast per voi nello stesso modo in cui lo fa per String <> PChar (spesso chiamato "magia del compilatore" - cioè la generazione del codice che si basa sul compilatore essere consapevoli dei propri interni). – Deltics

+0

@Ken: OK, capisco cosa intendi. Modifica la mia risposta. –

1

Due di questi tipi sono simili (identici infatti). Il terzo no.

tarray è dichiarato come "Array di Byte", come è Tbyte. Hai perso un altro tipo molto rilevante, tuttavia, TByteArray (il tipo di riferimento a PByteArray).

Essendo un puntatore TByteArray, PByteArray è propriamente un puntatore a una matrice di byte statico, non un array dinamico (che altri tipi array byte tutti sono). Viene digitato in questo modo per consentire il riferimento agli offset da quel puntatore di base utilizzando un indice intero. E nota che questa indicizzazione è limitata a 2^15 elementi (0,32767). Per offset arbitrarie byte (> 32767) da qualche puntatore base, un PByteArray non va bene:

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; 

cioè esprimono un matrice di Byte o un tarray ad un PByteArray è potenzialmente andando portare a problemi in cui l'array ha elementi> 32K (e il puntatore viene passato a un codice che tenta di accedere a tutti gli elementi). Il casting su un puntatore non tipizzato lo evita naturalmente (purché il "destinatario" del puntatore gestisca quindi l'accesso al riferimento di memoria tramite il puntatore in modo appropriato).

MA, nessuno di questi cambierà in futuro, è solo una conseguenza dei dettagli di implementazione che da tempo sono stati applicati in questo settore.L'introduzione di una dichiarazione di tipo generico sintatticamente zuccherata è una kipper rouge.

+0

Su un lato no, se ne sorge la necessità, il limite 32767 può essere aggirato ridichiando localmente il tipo in questo modo. tipo PByteArray =^TByteArray; TByteArray = array [0..MaxInt - 1] of Byte; –

+0

"Kipper rouge"? Cosa significa? –

+0

Siamo spiacenti - Kipper Rouge = "Red Herring" :) – Deltics