Visualizzazione dei risultati da 1 a 6 su 6

Discussione: [C] campi di bit

  1. #1
    Utente di HTML.it L'avatar di filips
    Registrato dal
    Sep 2011
    residenza
    Seconda stella a destra (questo e' il cammino)
    Messaggi
    155

    [C] campi di bit

    Ho letto questo:

    L'ordine dei campi di bit specificati dal programmatore e la corrispondenza con la rappresentazione interna dell'elaboratore dipende fortemente dalla implementazione, pertanto i campi di bit sono poco adatti a comunicare i dati con il mondo esterno.

    Non capisco cosa significhi. In che senso sarebbero poco indicati a comunicare dati con l'esterno?
    Per fare un tavolo ci vuole un fiore.

  2. #2
    Nel senso che non è una buona idea fare una fwrite di un bitfield e sperare di leggere con una fread il risultato con un programma fatto - ad esempio - con un altro compilatore, anche se lo si legge in un bitfield fatto nello stesso modo. Va detto comunque che questo si applica - anche se in misura minore - anche a qualunque struct non banale (per via di tutte le menate di packing/padding, oltre che per l'endianness dei numeri).
    Amaro C++, il gusto pieno dell'undefined behavior.

  3. #3
    Utente di HTML.it L'avatar di filips
    Registrato dal
    Sep 2011
    residenza
    Seconda stella a destra (questo e' il cammino)
    Messaggi
    155
    Buona risposta, penso che abbia chiarito la questione. Mi era venuto il vago sospetto che c'entrassero questioni architetturali, tuttavia non riuscivo a vederne il nesso. Quindi, se ho ben capito, salvare con un programma su una macchina X un bitfield, e poi effettuarne la lettura sulla medesima macchina da programma C diversamente compilato, sia pur com identica implementazione del dato nel sorgente, non garantisce coerenza del risultato, per via della diversa rappresentazione e interpretazione dei dati internamente al compilatore. Ma allora la questione non riguarda tanto l'architettura del calcolatore (che non cambia), piuttosto, interessa quella del compilatore, ovvero l'implementazione del compilatore (e questo non lo avevo affatto capito) non garantisce la medesima organizzazione del dato. Giusto?
    Ultima modifica di filips; 06-09-2016 a 14:28
    Per fare un tavolo ci vuole un fiore.

  4. #4
    Sì, anche se spesso sono considerazioni che alla fin della fiera derivano da come è fatto l'hardware. Per dire, il padding inserito nelle strutture in genere deriva da vincoli architetturali (per cui, ad esempio, accedere a certi tipi di dati è molto lento o addirittura non supportato se non sono allineati in memoria in una certa maniera), e in genere è roba che tutti i compilatori implementano alla stessa maniera su una data architettura.

    Sui bitfield ci sono due ulteriori arbitrarietà che non vengono dettate in maniera "ovvia" dall'architettura;
    - non è completamente scontata la dimensione delle word da usare per indirizzare la memoria che sta "dietro" il bitfield;
    - è arbitrario l'ordine in cui vengono messi i campi all'interno delle word in questione - si possono riempire da sinistra a destra come da destra a sinistra;
    - non è scontato cosa fare se un campo del bitfield finisce "a cavallo" tra una word e l'altra - si può fare la cosa efficiente in termini di spazio (tenere metà bit da una parte, metà dall'altra) o quella più efficiente in termini di performance (metterli tutti nella seconda word)

    Esempio:
    codice:
    struct A {
        int a: 5;
        int b: 10;
        int c: 16;
        int d: 15;
    };
    Immaginiamo di essere su una macchina a 32 bit: potremmo usare 2 word da 32 bit e impaccare tutto allineando "a destra":
    codice:
              DWORD 1                 |              DWORD 2
    31                             0  | 31                             0
    dccccccccccccccccbbbbbbbbbbaaaaa    __________________dddddddddddddd
    Oppure si potrebbe impaccare a sinistra:
    codice:
              DWORD 1                                DWORD 2
    31                             0  | 31                             0
    aaaaabbbbbbbbbbccccccccccccccccd    dddddddddddddd__________________
    Oppure si potrebbe evitare di stare inutilmente stretti, e lasciare un bit di padding sulla prima DWORD per evitare di fare due accessi separati e un milione di shift inutili per cavare fuori d
    codice:
              DWORD 1                 |              DWORD 2
    31                             0  | 31                             0
    _ccccccccccccccccbbbbbbbbbbaaaaa    _________________ddddddddddddddd
    Oppure passare a word da 16 bit e allineare tutto in maniera più intelligente, occupando meno spazio e ottenendo performance migliori (le letture e le scritture su c e su d diventano letture/scritture "normali" a 16 bit invece di necessitare di un mucchio di shift):
    codice:
          WORD 1             WORD 2           WORD 3
    15             0 | 15             0 | 15             0
    _bbbbbbbbbbaaaaa | cccccccccccccccc | _ddddddddddddddd
    Quindi insomma, sui bitfield c'è molta arbitrarietà, e il compilatore avrebbe abbastanza spazio di manovra per fare un po' quel che gli pare e ottimizzare al meglio.

    Ora, in realtà su piattaforme "moderne" di solito è ben definita una ABI di qualche genere che specifica esattamente questo tipo di dettagli di basso livello - dalle convenzioni di chiamata (in quali registri vengono passati i parametri, chi è responsabile della pulizia dello stack dopo la chiamata, quali registri sono preservati, ...) al layout delle struct C; questo è necessario altrimenti non sarebbe possibile l'interazione anche solo tra programmi e sistema operativo.
    Le ABI in genere specificano anche come devono essere gestiti tutti questi casini dei bitfield, per cui, data una determinata piattaforma (per dire Linux su x86_64), la sua ABI (nel caso in questione, la ABI System V adattata per x86_64) e preso un compilatore che aderisce alla ABI (gcc, clang, icc), tutti questi dovrebbero alla fine produrre la stessa rappresentazione per un bitfield specificato alla stessa maniera (a patto di stare nelle regole specificate dalla ABI).

    Ciò detto, tutto questo è assolutamente irrilevante visto che in 10 anni di C e C++ credo di aver visto usare i bitfields "per davvero" forse due volte.
    Amaro C++, il gusto pieno dell'undefined behavior.

  5. #5
    Utente di HTML.it L'avatar di filips
    Registrato dal
    Sep 2011
    residenza
    Seconda stella a destra (questo e' il cammino)
    Messaggi
    155
    Eheh.. Sarà anche irrilevante, ma io non ne potevo più di non capirci una mazzolina.. In pratica ragionavo tenendo fissato il compilatore, e allora diventava incomprensibile il discorso: se il compilatore è invariato ed è in grado di girare su una macchina, che ci sia un ordine dei byte o un altro, non dovrebbe interferire quando il programma va a prelevare un dato - mi dicevo..
    Grazie mille per l'ottima esaustiva risposta!
    Per fare un tavolo ci vuole un fiore.

  6. #6
    Amaro C++, il gusto pieno dell'undefined behavior.

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 © 2024 vBulletin Solutions, Inc. All rights reserved.