Newsgroup: it.comp.lang.visual-basic
Titolo: [?] Puntatori e strutture

Ok, offro il pranzo al prossimo raduno a chi riesce a risolvermi questo.
Ho una struttura di tipo TRecord (sotto la definizione).
Ho due sub che stanno in due classi differenti, per cui niente passaggio del
tipo TRecord tra i parametri.
Pensavo bastasse usare la VarPtr() per passare il puntatore (Long) e poi
fare l'inverso nella seconda sub per riottenere il contenuto della mia var,
ma niente.
Allora ho pensato di trasferire il contenuto di una struttura in un array di
byte e poi ritravasare il tutto nella seconda struttura... funziona, ma non
capisco perchč devo usare una dimensione di byte pari a LenB(Rec) anzichč
Len(rec) (che secondo i miei conti sarebbe anche corretta).
In pratica:
Classe1.Sub1()
    Dim Rec as TRecord
    Call Classe2.Sub2(qui devo far passare Rec)
End sub
Classe1.Sub2(da qui dovrebbe arrivare Rec in qualche modo)
    Dim Rec2 as TRecord
    Rec2 = Rec ' o meglio ancora Rec2 punta a Rec
End sub
La dichiarazione di TRecord č la seguente
Public Type TRecordHeader
    Status As String * 1
    ReservedBytes(1 To 3) As Byte ' to keep multiple of 4
    lOffset As Long
    lLength As Long
    lPrev As Long
    lNext As Long
End Type  ' 20 bytes
Public Type TField
    Size As Long        ' stream size
    Value() As Byte     ' stream value
End Type ' 4 + 4(Value ptr) bytes
Public Type TRecord
    Header As TRecordHeader
    Reserved(1 To 4) As Long
    Fields() As TField
End Type ' 20 + 16 + 4(Fields ptr) bytes
Grazie a tutti

 soluzione piu' in stile OOP.
Lo so, ma volevo una soluzione di piů basso livello senza scomodare una
classe solo per quest'unico passaggio.
Ciao

 della struttura (infatti LenB(Rec) = Len(Rec) + 4).
Non mette nessun puntatore, ma aggiunge 4 byte di allineamento.
Ciao.

 di allineamento.
Guardando si intuisce bene dove aggiunga i byte di allineamento:
nella struttura TRecordHeader.
Public Type TRecordHeader1
    Status As String * 1 'qui aggiunge 3 byte
    ReservedBytes(1 To 3) As Byte ' qui ne aggiunge un altro
    lOffset As Long
    lLength As Long
    lPrev As Long
    lNext As Long
End Type  ' 20 bytes - in realta' la struttura occupa in memoria 24
byte
Ciao.

"H.P.L." <u...@vaila.ble> ha scritto nel messaggio
news:l8Ud7.549$Ft4....@news.infostrada.it...

Mi spiace, ma non č cosě :)
Oggi sono riuscito a farlo funzionare cosě:
        RecordPtr = VarPtr(p_Record)
E nell'altra sub ricavo una copia con
    Call CopyMemory(ByVal VarPtr(Record), ByVal RecordPtr, LenRecord)
La cosa veramente divertente č che devo farmi una copia di backup della
struttura prima della copymemory per poi ripristinarla prima di uscire dallo
scope della sub, pena un GPF!
Ho scoperto anche il perchč: sembra che vengano copiati puntatori ai
descrittori dell'array Fields() in TRecord, solo che uscendo dallo scope
della sub vengono rilasciate le risorse associate, che perň non erano state
associate lě!
Il problema č sempre stato quello dell'array Fields() solo che non capivo
come accidenti lo gestiva VB finchč non ho visto questo GPF...
Ciao

 Oggi sono riuscito a farlo funzionare così:
[cut]
Hai ragione. Dimenticavo che le stringhe sono unicode.
I byte di padding vengono aggiunti cosi':
Public Type TRecordHeader
    Status As String * 1 'occupa 2 byte
    ReservedBytes(1 To 3) As Byte 'qui vengono aggiunti 3 byte di
allineamento
    lOffset As Long
    lLength As Long
    lPrev As Long
    lNext As Long
End Type  ' la struttura occupa in memoria 24 byte e non 20.
Ciao.

 End Type  ' la struttura occupa in memoria 24 byte e non 20.
Mannaggia!
Vuoi dire che String * 1 occupa ugualmente i 4 bytes del puntatore?
Eh, già... altrimenti come farebbe con String * 5?
Ciao

 4 bytes del puntatore?
No, no. All'interno di una struttura le stringhe a lunghezza
variabile (String) sono diverse
dalle stringhe a lunghezza fissa (String * x).
Le prime vengono memorizzate nella struttura come un puntatore ed
occupano quindi sempre e solo 4 byte indipendentemente dalla loro
lunghezza.
Per quanto riguarda le ultime i vengono invece memorizzati
all'interno della struttura tutti i byte (essendo Unicode, 2 byte
per ogni carattere) che compongono la stringa.
Quindi String * 1 occupa 2 byte, String * 5 occupa10 byte.
Inoltre all'interno di una struttura viene mantenuto per ragioni di
efficienza un certo allineamento, per cui vengono eventualmente
aggiunti byte di padding per ottenere questo allineamento.
In questo caso:
Public Type TRecordHeader
    Status As String * 1
    ReservedBytes(1 To 3) As Byte
    lOffset As Long
    lLength As Long
    lPrev As Long
    lNext As Long
End Type  ' 20 bytes
vengono aggiunti dopo String * 1 e (1 to 3) As Byte, che occupano
rispettivamente 2 e 3 byte, 3 byte di padding per portare
l'allineamento agli 8 byte.
Ciao.

 10 byte? Mah, erano tanto semplici le char* in C...
Le stringhe VB alla fine sono memorizzate in "semplici" wchar_t*.
P.S.
Mi spieghi dove vedi la semplicita' dei char* in C?
Ciao.

> 10 byte? Mah, erano tanto semplici le char* in C...
HPL> Le stringhe VB alla fine sono memorizzate in "semplici" wchar_t*.
HPL> P.S.
HPL> Mi spieghi dove vedi la semplicita' dei char* in C?
Semplici, carini,  un byte  per carattere ed  un terminatore  in fondo
nello heap, niente orpelli aggiuntivi nello stack o nel segmento data.
Se passi a caratteri di 2  byte nessun problema, tanto se definisci un
tipo a 16 bit  ed il tappo come 2 byte a  0 l'aritmetica dei puntatori
funziona ancora  ed il fatto  che a fine  stringa il puntatore  char *
punta a qualcosa che vale zero... (ovvio che se gestisci dati a 2 byte
con un tipo di size 1 allora la cosa si complica).
La memorizzazione  delle stringhe in  VB, volendo tenere  la struttura
che  c'era sul  Vic20  :)  in onore  al  nome Basic,  č  un pelin  piů
incasinata.   Ma  siamo  sempre  sul  S.O.  scritto  in  C  usando  la
convenzione di chiamata del  Pascal... Perň potevano mettersi ad usare
la  convenzione del  FORTRAN  una funzione  si  ed una  no  e fare  lo
scheduler dei task in LISP... :)
--
Gian Uberto| main(){printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}
Lauri      |                        David Korn, 1987 ioccc best one liner 
(aka saint)|-------------------------------------------------------------------
em@ail: 
sa...@eng.it
 ( vedere X-nospam nello header - see X-nospam in header )

 data.
[cut]
Fonte di numerosi errori e malfunzionamenti.
Infinitamente meglio utilizzare std::string (come dici? In C non
c'e'? Solo i malati di mente utilizzano il C con il C++ a
disposizione :-P).
Ciao.

>>>> "HPL" == H P L <u...@vaila.ble> writes:
HPL> Fonte di numerosi errori e malfunzionamenti.
In mano alle  persone sbagliate. Mai avuto un  singolo problema con le
stringhe.
HPL> Infinitamente meglio utilizzare std::string (come dici? In C non
HPL> c'e'? Solo i malati di mente utilizzano il C con il C++ a
HPL> disposizione :-P).
Cavolata. A me ad esempio il C++ piace per niente e non sono il solo.


 per niente e non sono il solo.
Non lo apprezza chi non lo conosce.
Sinceramente non trovo un solo motivo valido (non valgono quindi i
"non conosco il C++", "non ho un compilatore", "mi obbligano ad
usare il C",
ecc..)  per preferire il C al C++.
Chiaramente poi uno e' libero di farsi del male come preferisce.
Comunque chiudiamo qui perche su questo NG siamo veramente troppo
OT.
Ciao.