Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 20
  1. #1
    Utente di HTML.it L'avatar di giudf
    Registrato dal
    Jun 2006
    Messaggi
    162

    Ordinamento dei byte

    Ragazzi, ho un problemuccio abbastanza grande e spero che qualcuno mi possa aiutare:

    Mentre sfogliavo manuali per cercare funzioni C che riuscissero a trasformare un valore da Network Byte Order ad Host Byte Order e viceversa ho trovato htons e htonl,

    sfortunatamente queste 2 funzioni non vanno bene se il valore da convertire come nel mio caso è un double.

    Morale della favola, devo farmi una funzioncina io per i double

    Ora la domanda è:

    1) Come faccio a capire se un valore è ordinato dalla cifra + significativa o viceversa ? (Little Endian o Big Endian)

    2)Come cacchio faccio a scindere i byte del mio double ed invertirli (invertirli non srebbe neanche tanto difficile) ma come li scompongo ?

    Spero qualcuno mi aiuti !!!

  2. #2
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,480
    Devi chiarire alcuni punti ...

    1) il formato dei double che ti arrivano dovrebbe esserti noto; come mai non lo conosci?

    2) l'ordine dei byte non si puo' assolutamente dedurre (con certezza) dal valore; ma tale ordine dovrebbe essere anch'esso conosciuto sapendo da dove arrivano i valori ...

    3) non puoi "scomporre" il valore double; se il formato (non solo l'ordine dei byte) e' diverso da quello standard, devi anche "convertirlo" e per farlo devi conoscere il formato di partenza e quello di arrivo.

    Detto questo, la domanda piu' importante e' : da dove vengono questi valori ...?

  3. #3
    Utente di HTML.it L'avatar di ibykos
    Registrato dal
    Feb 2005
    Messaggi
    201
    C'è un trucco per scomporli.
    L'invenzione probabilmente risalve a San R. W. Stevens, ma l'attribuzione è incerta :-), in ogni caso eccotela:

    codice:
    #include <stdio.h>
    
    int main ()
    {
      union {
        short s;
        char c [ sizeof(short) ];
      } u;
    
      u.s = 0x0102;
    
      if (sizeof(short) == 2)
      {
        if (u.c[0]==0x01 && u.c[1]==0x02)
          puts ("big-endian");
        else if (u.c[0]==0x02 && u.c[1]==0x01)
          puts ("little-endian");
        else
          puts ("unknownn");
      }
      else
        printf ("can't perform my duty: sizeof(short) = %d != 2\n", sizeof(short));
    
      return 0;
    }
    Il trucco sta nell'usare il costrutto union per operare una vista su un dato: nel tuo caso basta che dichiari

    codice:
      union {
        double s;
        char c [ sizeof(double) ];
      } u;
    In ogni caso lo scopo di questa funzione è determinare se una macchina è little endian o big endian e non è modificare un dato in modo così "sporco".
    Oregon ha ragione su tutta la linea.
    Ciao!

  4. #4
    Utente di HTML.it L'avatar di giudf
    Registrato dal
    Jun 2006
    Messaggi
    162

    Chiarimenti

    Dunque, per entrare nello specifico io devo fare un programma che abbia il valore long memorizzato in Network Byte Order (e memorizzarlo poi successivamente su un file) perchè la macchina al quale lo devo consegnare, deve vederlo con quell'ordinamento.
    Siccome ho finora utilizzato l'htons e l'htonl, nn mi è mai interessato entrare nello specifico per vedere come erano ordinati i byte sulla mia macchina perchè facevo

    htons(value_to_convert);

    e me ne lavavo le mani, perchè la suddetta funzione verifica se il valore è memorizzato in HBO, se è così lavora scambiando i byte, altrimenti lo tralascia.

    Ora come faccio a fare la stessa cosa con i double ?

  5. #5
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,480
    Hai ripresentato la stessa domanda esattamente come se non ti avessi risposto ... comunque ...

    Se utilizzi le funzioni di cui hai parlato, vengono semplicemente scambiati il primo con il quarto byte e il secondo con il terzo (o, per la versione a 16 bit, solo il primo con il secondo) ...

    Se devi fare lo stesso lavoro con un double, devi lavorare su 8 byte (il primo con l'ottavo, il secondo con il settimo, il terzo con il sesto, il quarto con il quinto) in maniera abbastanza semplice ... Un semplice esempio potrebbe essere

    codice:
    union _u
    {
      double d;
      unsigned char c[8];
    };
    
      union _u sr, ds;
    
      // In sr.d il valore double originale
    
      for(int i=0; i<8; i++)
         ds.c[7-i]=sr.c[i];
    
      // In ds.d il valore double modificato
    Se in tal modo non si interferisce con il formato del double, allora questa operazione e' sufficiente ...

  6. #6
    Utente di HTML.it L'avatar di giudf
    Registrato dal
    Jun 2006
    Messaggi
    162

    Testing

    Ti ringrazio,
    Mi spiace nn essere stato molto chiaro, nonostante ciò la tua risposta è abbastanza esaustiva, a questo punto però sorgono dei problemucci:

    1)Come la testo la tua funzioncina?
    Io l'avevo pensata così, correggimi se sbaglio:

    Dunque quello che faccio è invertire l'ordine dei byte quindi se un 2 in binario è rappresentato da 00000010 con la conversione dovrà essere 01000000 e dovrà darmi il numero corrispondente sbaglio?

    2)Ho pensato anche al fatto che quell'8 sul tuo codice non è portabile, perchè non so a priori l'architettura della macchina al quale devo mandarla (e se non sbaglio il double cambia di dimensioni da 32 bit a 64 bit) quindi lo sostituirò con un sizeof(double) a questo punto però posso sostituire il 7-i con un ((sizeof(double)-1)-i) ? Penso il compilatore la accetti un espressione del genere!


    Ti ringrazio infinitamente !!!!

    P.S Magari non sono stato molto chiaro, ma mettendo il double su file, l'ordine dei byte diventa molto importante perchè quando lo vado a leggere deve essere in Network Byte Order.
    Detto ciò mi viene in mente un altra domanda, c'è il modo per sapere che tipo di ordinamento fà la mia macchina?

  7. #7
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,480

    Re: Testing

    Originariamente inviato da giudf
    1)Come la testo la tua funzioncina?
    Io l'avevo pensata così, correggimi se sbaglio:

    Dunque quello che faccio è invertire l'ordine dey byte quindi se un 2 in binario è rappresentato da 00000010 con la conversione dovrà essere 01000000 e dovrà darmi il numero corrispondente sbaglio?
    No ... stai ragionando in binario puro (come se fosse un intero). Un double e' in un formato particolare standardizzato, formato da mantissa ed esponente (IEEE standard, leggi http://www.psc.edu/general/software/...ieee/ieee.html) e quindi e' difficile ragionare nel modo che indichi. Era quello che ti volevo dire sin dall'inizio ...

    L'unico modo di testare la funzione e' sapere quale era il valore double in arrivo e quale e' quello dopo l'inversione nel tuo sistema.

    Per fare questo confronto *devi* sapere quali sono i valori che ti arrivano *prima* di essere invertiti ...

    Originariamente inviato da giudf
    2)Ho pensato anche al fatto che quell'8 sul tuo codice non è portabile, perchè non so a priori l'architettura della macchina al quale devo mandarla (e se non sbaglio il double cambia di dimensioni da 32 bit a 64 bit) quindi lo sostituirò con un sizeof(double) a questo punto però posso sostituire il 7-i con un ((sizeof(double)-1)-i) ? Penso il compilatore la accetti un espressione del genere!
    Il formato su 8 byte occupa 64 bit. Questo anche su macchine a 32.
    Ripeto ancora ... dipende dal formato del valore double che utilizzi.

    Utilizzando il sizeof il programma considera *sempre* la dimensioni dei double nel sistema in cui viene eseguito ma non prende in considerazione quelle del valore che gli arriva dall'esterno ... perche' non puo' sapere se il valore gli arriva da una macchina in cui il formato del double, sebbene in ordine inverso, sia di dimensioni e/o formato diversi ...

    Originariamente inviato da giudf
    P.S Magari non sono stato molto chiaro, ma mettendo il double su file, l'ordine dei byte diventa molto importante perchè quando lo vado a leggere deve essere in Network Byte Order.
    Questo l'ho capito ... Il problema maggiore di questa discussione e' che tu *non hai ancora detto* da dove ti arrivano questi valori. E se conosci da dove ti arrivano sai anche in quale formato sono ...

    E' un segreto? Che programma stai scrivendo?

    Originariamente inviato da giudf
    Detto ciò mi viene in mente un altra domanda, c'è il modo per sapere che tipo di ordinamento fà la mia macchina?
    Quello dipende *unicamente* dalla CPU. Se, come penso, la tua macchina utilizza una INTEL x86, allora utilizzi il "little-endian byte order".

  8. #8
    Utente di HTML.it L'avatar di giudf
    Registrato dal
    Jun 2006
    Messaggi
    162

    Non lo so che tipo di ordinamento ha

    .. Ma ho trovato 1 cosa molto interessante

    #include<endian.h>
    ...
    #if __BYTE_ORDER==__LITTLE_ENDIAN
    ...
    #endif
    #if __BYTE_ORDER==__BIG_ENDIAN
    ...
    #endif

    Sembrerebbero essere delle costanti della libreria endian.h che mi aiutano a verificare l'ordinamento

    Penso che così sia + semplice, ora se l'if è verificata uso la tua funzioncina altrimenti ";" a tale proposito però volevo chiederti : Posso schiaffare il mio double in un vettore di char (quindi 1 byte)
    char *vett = calloc(sizeof(double),sizeof(char));

    e poi fare una semplice inversione da vettore senza usare la union?

    Comunque ciò che sto facendo non è che sia Top Secret, è un banale progetto universitario di laboratorio Programmazione 2, l'ultimo dei 4 moduli :

    http://twiki.dsi.uniroma1.it/pub/Lab...l/modules.html
    n

  9. #9
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,480
    Se stai lavorando con Linux va bene ... non con Windows.

    Puoi includere qualcosa del genere ...

    codice:
    #if defined(i386) || defined(__i386__) || defined(__i386) || \
          defined(_M_IX86) || defined(_X86_) || defined(__THW_INTEL) || \
          defined(sun386)
    #define BYTE_ORDER      LITTLE_ENDIAN
    #endif
    Puoi usare il vettore di char ma l'union e' piu' comoda ...

  10. #10
    Utente di HTML.it L'avatar di giudf
    Registrato dal
    Jun 2006
    Messaggi
    162

    Vettore di char

    Usando il vettore di char, un assegnamento del tipo vett = val dove val è il valore double non mi sembra corretto, che dici se faccio una

    memcpy(&vett[0],&val,sizeof(double))

    in questo modo dovrebbe riempirmelo correttamente credo !!!

    Altrimenti potrei usare la union che mi hai suggerito, ma non ho tanta familiarità con le union perchè non ne ho mai avuto il bisogno, ho sempre usato solo struct (Sembrerebbe che al contrario della struct i valori sono strettamente dipendenti l'uno dall'altro), mi sono documentanto ma nn è che ci ho capito granchè!

    Ad ogni modo rimarro sempre nel dubbio visto che non ho il modo di testarlo, smontando infatti la mia tesi del test precedente, non mi viene un altra idea buona per verificare se la conversione viene effettuata correttamente!!!

    Ce l'hai un illuminazione a portata di mano?

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.