Pagina 1 di 2 1 2 ultimoultimo
Visualizzazione dei risultati da 1 a 10 su 16
  1. #1
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320

    [C] Dimensione struct non torna

    Salve a tutti.
    Mi sono trovato di fronte ad un problema alquanto fastidioso.
    Io ho a che fare con una struct di questo tipo:
    codice:
    struct MioHeader {
       int    HD_first;
       char   HD_dsc[16];
       int    HD_second;
       INT64  HD_time1;
       INT64  HD_time2;
       INT64  HD_time3;
       int    HD_third;
       int    HD_begin;
       int    HD_end;
    };
    Se provo a stampare le dimensioni di ciascun tipo, come da codice seguente:
    codice:
    printf("Dimensione int: %d\n", sizeof(int));
    printf("Dimensione char: %d\n", sizeof(char));
    printf("Dimensione INT64: %d\n", sizeof(INT64));
    ottengo, correttamente, questo output:
    codice:
    Dimensione int: 4
    Dimensione char: 1
    Dimensione INT64: 8
    Quello che non mi torna è la dimensione della struttura, che a mio avviso, date le condizioni precedenti, dovrebbe essere 60 byte. In realtà, questo codice:
    codice:
    printf("Dimensione struct: %d\n", sizeof(struct MioHeader));
    mi stampa a video il valore 64. Se provo a salvare su file i byte della struttura, infatti, noto che subito dopo i tre campi INT64 vengono piazzati 4 byte (tutti con valore 0) che non so proprio da dove vengano...

    Chi mi risolve questo arcano?

    Grazie mille.

    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

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

    Per motivi di efficienza, tutti i compilatori allineano le strutture in memoria.
    Per molti compilatori l'allineamento di default e' agli 8 byte cosicche' i byte che mancano sono effettivamente allocati ma non usati.

    Non so quale compilatore utilizzi, ma in genere esistono dei parametri di compilazione con cui e' possibile modificare questo comportamento.

    Con VC, ad esempio, per allineare le strutture al byte si usa l'opzione /Zp1

  3. #3
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Ma allora come mai i 4 byte in più vengono inseriti subito dopo i due valori INT64?


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  4. #4
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,480
    Io ho visto in debug la memoria e i byte sono aggiunti alla fine della struttura ...

    Tu come lo hai controllato?

    Quale compilatore usi?

  5. #5
    Ciao,
    per cambiare il packing a 1 (cioè il compilatore allinea i membri a byte e quindi non aggiunge
    altri byte spuri) di una sola struttura puoi anche usare la seguente pragma:
    codice:
    #pragma pack(push, 1)
    struct ....
    #pragma pack(pop)
    sicuramente funziona con il Visual su Windows e con il gcc su linux/windows.

  6. #6
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Sto utilizzando Dev-Cpp.
    Ho notato che i byte in più vengono messi immediatamente dopo i due INT64 perchè ho assegnato ovviamente dei valori alle altre variabili in modo inequivocabile. Inoltre ho provato a spostare quei campi all'interno della struct.
    Ho salvato la struttura su un file e l'ho aperto con un editor esadecimale.


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  7. #7
    Utente di HTML.it L'avatar di oregon
    Registrato dal
    Jul 2005
    residenza
    Roma
    Messaggi
    36,480
    Mostrami il codice che hai usato che lo provo con DevCpp ...

  8. #8
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Lo posto domani... ora non ho quel codice sotto mano... non sono nel mio ufficio.

    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  9. #9
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Eccomi nel mio ufficio.
    Posto l'intero programma e il dump del file che ne esce:
    codice:
    #include <stdio.h>
    #include <windows.h>
    
    struct Mio_Header {
       int    HD_magic_byte;
       char   HD_GUID[16];
       int    HD_flags;
       int    HD_FileAttribute;
       INT64  HD_Time1;
       INT64  HD_Time2;
       INT64  HD_Time3;
       int    HD_FileLength;
       int    HD_INumber;
       int    HD_ShowWnd;
       int    HD_HKey;
       int    HD_Reserved[2];
    } the_header;
    
    int main(int argc, char **argv) {
       
       FILE *fileOut;
                         
       the_header.HD_magic_byte = -1;
       the_header.HD_GUID[0] = (char) 0xFF;
       the_header.HD_GUID[1] = (char) 0xFF;
       the_header.HD_GUID[2] = (char) 0xFF;
       the_header.HD_GUID[3] = (char) 0xFF;
       the_header.HD_GUID[4] = (char) 0xFF;
       the_header.HD_GUID[5] = (char) 0xFF;
       the_header.HD_GUID[6] = (char) 0xFF;
       the_header.HD_GUID[7] = (char) 0xFF;
       the_header.HD_GUID[8] = (char) 0xFF;
       the_header.HD_GUID[9] = (char) 0xFF;
       the_header.HD_GUID[10] = (char) 0xFF;
       the_header.HD_GUID[11] = (char) 0xFF;
       the_header.HD_GUID[12] = (char) 0xFF;
       the_header.HD_GUID[13] = (char) 0xFF;
       the_header.HD_GUID[14] = (char) 0xFF;
       the_header.HD_GUID[15] = (char) 0xFF;
       the_header.HD_flags = -1;
       the_header.HD_FileAttribute = -1;
       the_header.HD_Time1 = (INT64) -1;
       the_header.HD_Time2 = (INT64) -1;
       the_header.HD_Time3 = (INT64) -1;
       the_header.HD_FileLength = -1;
       the_header.HD_INumber = -1;
       the_header.HD_ShowWnd = -1;
       the_header.HD_HKey = -1;
       the_header.HD_Reserved[0] = the_header.HD_Reserved[1] = -1;
    
       if ((fileOut = fopen("prova.dat", "wb")) == NULL) {
          printf("Errore nella creazione del file!\n\n");
          exit(1);
       }
       
       fwrite(&the_header, sizeof(struct Mio_Header), 1, fileOut);
       
       fclose(fileOut);
    
    
       return 0;
    }
    Ecco il dump del file "prova.dat" prodotto dal programma:
    codice:
    0000   ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
    0010   ff ff ff ff ff ff ff ff ff ff ff ff 00 00 00 00
    0020   ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
    0030   ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
    0040   ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
    Come si può notare ci sono quei 4 byte a zero esattamente prima dei tre valori INT64 (mi sono accorto che nei post precedenti avevo scritto "dopo", non avendo il codice davanti...).

    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

  10. #10
    Moderatore di Programmazione L'avatar di LeleFT
    Registrato dal
    Jun 2003
    Messaggi
    17,320
    Io sono un tipo curioso.
    Così, ho provato ad aggirare il problema. Ho sostituito i tre valori INT64 con 3 array di interi da due elementi (quantitativamente le dimensioni non cambiano, con interi a 4 byte) e, come per magia, tutto è andato a posto: i byte sono effettivamente 76 e posizionati come voglio io.


    Ora mi rimane di capire perchè, se utilizzo il tipo INT64 succedono queste cose...


    Ciao.
    "Perchè spendere anche solo 5 dollari per un S.O., quando posso averne uno gratis e spendere quei 5 dollari per 5 bottiglie di birra?" [Jon "maddog" Hall]
    Fatti non foste a viver come bruti, ma per seguir virtute e canoscenza

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.