Autore Topic: Emulare il "signed char" del C  (Letto 547 volte)

Offline vuott

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 11.307
  • Ne mors quidem nos iunget
    • Mostra profilo
Emulare il "signed char" del C
« il: 09 Gennaio 2020, 16:11:28 »
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:
Codice: [Seleziona]
' 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)
Codice: [Seleziona]
Print "\nDa Gambas: "; CShort(Byte@(p)) - 256
o peggio:
2)
Codice: [Seleziona]
Print "\nDa Gambas: "; Val("&" & Hex(Byte@(p))) - 256

La domanda è:
avete una soluzione migliore rispetto a quella del punto 1) ?
« Ultima modifica: 11 Gennaio 2020, 16:51:45 da vuott »
« Chiunque, non ricorrendo lo stato di necessità, nel proprio progetto Gambas fa uso delle istruzioni Shell o Exec, è punito con la sanzione pecuniaria da euro 20,00 a euro 60,00. »

Offline Top Fuel

  • Gran Maestro dei Gamberi
  • *****
  • Post: 960
    • Mostra profilo
Re:Emulare il "signed char" del C
« Risposta #1 il: 11 Gennaio 2020, 16:31:54 »
Io ho trovato questa maniera, non so se sia migliore ma non usa gli Short:  :-\

Codice: [Seleziona]
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
Dear youtube administrators, your search bar is broken. When I type the letter "J" it appears justin bieber when it should appear Jimi Hendrix. Fix this, please.

Offline vuott

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 11.307
  • Ne mors quidem nos iunget
    • Mostra profilo
Re:Emulare il "signed char" del C
« Risposta #2 il: 11 Gennaio 2020, 16:47:17 »
Io ho trovato questa maniera
Apprezzo sinceramente lo sforzo, ed è interessante (anche sotto il profilo didattico) l'analisi a livello dei bit, però il segno meno lo impone artificialmente il codice.
Cercavo invece qualcosa di "automatico", come nelle mie due soluzioni.

Comunque ti ringrazio molto.  :ok:
« Ultima modifica: 11 Gennaio 2020, 16:49:20 da vuott »
« Chiunque, non ricorrendo lo stato di necessità, nel proprio progetto Gambas fa uso delle istruzioni Shell o Exec, è punito con la sanzione pecuniaria da euro 20,00 a euro 60,00. »

Offline Top Fuel

  • Gran Maestro dei Gamberi
  • *****
  • Post: 960
    • Mostra profilo
Re:Emulare il "signed char" del C
« Risposta #3 il: 11 Gennaio 2020, 19:58:35 »
Automatico è un pò difficilino senza usare gli Short.... :)
Comunque ho usato la variabile stringa per poter eventualmente creare una funzioncina ad hoc nel caso servisse, inoltre ho scoperto dopo che in questa maniera rispetto al C abbiamo un numero in più, infatti il range va da +127 a -128, e non è sbagliato.
Infatti guarda qui (sezione Particolarità):  ;)
https://it.wikipedia.org/wiki/Complemento_a_due
Dear youtube administrators, your search bar is broken. When I type the letter "J" it appears justin bieber when it should appear Jimi Hendrix. Fix this, please.

Offline vuott

  • Moderatore globale
  • Senatore Gambero
  • *****
  • Post: 11.307
  • Ne mors quidem nos iunget
    • Mostra profilo
Re:Emulare il "signed char" del C
« Risposta #4 il: 13 Gennaio 2020, 02:23:10 »
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
Codice: [Seleziona]
If Byte@(p) > 127 Then
    Print (256 - (Byte@(p) - 256)) * -1
  Else
    Print Byte@(p)
  Endif
« Ultima modifica: 13 Gennaio 2020, 03:20:08 da vuott »
« Chiunque, non ricorrendo lo stato di necessità, nel proprio progetto Gambas fa uso delle istruzioni Shell o Exec, è punito con la sanzione pecuniaria da euro 20,00 a euro 60,00. »