Come è noto, Gambas riguardo ai tipi di dati deficita un po' rispetto alla disponibilità offerta dal C.
Ad esempio in Gambas non esistono lo Short, l'Integer e il Long "senza segno".
...non esiste neppure il Byte "con segno".
Infatti, come sappiamo il tipo "Byte" è in grado di rappresentare numeri che vanno da 0 fino a 255 (per un complessivo di 256 valori rappresentabili).
In C il suo corrispondente "char" è disponibile sia nella modalità "senza segno" (come il "Byte" di Gambas) che in quella "con segno", capace di rappresentare numeri che vanno da -127 a +127.
Solitamente in Gambas noi risolviamo agevolmente l'assenza del tipo Byte "con segno" usando un tipo di dati superiore (ad esempio con lo Short).
Ciò può, però, creare problemi quando si deve procedere ad una lettura di un solo byte cruda e diretta di un'area di memoria allocata, puntata da un Puntatore, oppure quando si ottiene un valore analogo (di un solo byte) da una funzione esterna, che però deve essere rappresentato in negativo.
Mi spiego meglio: ottengo il valore 222 (&hDE), ma deve essere poi ad esempio rappresentato e visualizzato in console come -34.
Mostro un codice pratico di quel che ho detto:
' void scrivechar(char * po)
Private Extern scrivechar(po As Pointer) In "/tmp/libbyte"
Public Sub Main()
Dim p As Pointer
p = Alloc(SizeOf(gb.Byte), 2)
Creaso()
' Passa alla funzione esterna l'area, sopra allocata, puntata dalla variabile di tipo Puntatore "p",
' affinché tale funzione esterna vi scriva un valore che occupi un solo byte (char) di memoria:
scrivechar(p)
' Dereferenzia il Puntatore, per ottenere il valore scritto dal codice C.
' Sottrae 256 al valore ritornato, per ottenere lo speculare negativo.
Print "\nDa Gambas: "; Byte@(p) - 256
Free(p)
End
Private Procedure creaso()
File.Save("/tmp/libbyte.c", "#include <stdio.h>\n"
"void scrivechar(char * po) {\n"
" *po = 222;\n"
" printf(\"Dal C: %d\\n\", *po);\n}")
Shell "gcc -o /tmp/libbyte.so /tmp/libbyte.c -shared" Wait
End
Potete vedere la differenza dei risultati.
(Non capisco :-\ perché, ricavando il valore dalla funzione Byte@(), poi non fa la sottrazione. ...ma questo forse dovrei domandarlo nella Mailing List di gambas.)
Per emulare il "signed char" del C, ho dovuto escogitare questa modalità:
1) Print "\nDa Gambas: "; CShort(Byte@(p)) - 256
o peggio:
2) Print "\nDa Gambas: "; Val("&" & Hex(Byte@(p))) - 256
La domanda è:
avete una soluzione migliore rispetto a quella del punto 1) ?
Io ho trovato questa maniera, non so se sia migliore ma non usa gli Short: :-\
Public Sub Form_Open()
Dim numero As Byte = 222
Dim numeroconsegno As String
If BTst(numero, 7) = True Then 'se il bit più a sinistra vale 1 allora è negativo
numeroconsegno = "-" & Str$(numero - (numero - 128) * 2)
Print "\nDa Gambas :"; numeroconsegno
Endif
End
Non sono soddisfatto delle mie soluzioni, poiché funzionano solo se il valore è superiore a +127.
Se voglio ottenere un comportamento abbastanza coerente con il "signed char" devo usare un IF: :-X
If Byte@(p) > 127 Then
Print (256 - (Byte@(p) - 256)) * -1
Else
Print Byte@(p)
Endif