structs und padding



  • argh ich versuche schon den ganzen tag ein programm zu schreiben dass eine wave datei ausgibt und hab mich immer gewundert dass es nicht geht bis ich herausgefunden habe dass es an den padding bytes liegt die meinen schönen wav-header struct der eigentlich 44byte groß sein soll 48 bytes groß machen.

    gibt es irgendeine andere möglichkeit sowas zu machen als die sachen in ein struct zu packen und dass dann zu speichern?

    ich hab gehört dass man diese padding bytes ausmachen kann aber dass sollte eigentlich die letzte möglichkeit sein weil das so compilerspezifisch ist



  • würde sagen: falsches forum

    schau dir mal bekannte tools zur bearbeitung von waves und mp3 (diese die open source sind) an, solltest deine antwort dort finden



  • aoeu schrieb:

    ich hab gehört dass man diese padding bytes ausmachen kann aber dass sollte eigentlich die letzte möglichkeit sein weil das so compilerspezifisch ist

    Yep. Die meisten (eigentlich alle mir bekannten) Compiler bieten Optionen, die Strukturausrichtung anzupassen. Aber wie du schon sagst, das sollte der letzte Ausweg sein.

    So spontan fallen mir zwei Lösungen für dein Problem ein:
    1. Das Padding der Struktur einfach verwerfen

    wav_header_struct wav_header;
    // statt
    lese_datei(reinterpret_cast<char*>(&wav_header), sizeof(wav_header));
    // folgendes
    lese_datei(reinterpret_cast<char*>(&wav_header), 44);
    

    2. Plain lesen und dann Bit für Bit interpretieren, zB

    char wav_header[44];
    lese_datei(wav_header, 44);
    //...
    uint32 length = *reinterpret_cast<uint32*>(&wav_header[4]);
    //...
    


  • hm es geht mir ja mehr ums schreiben von wave dateien und ich denke wenn ich da nicht sizeof(wheader) nehme kommt müll raus wenn die paddingbytes nicht am ende sind... aber ich probier mal noch rum.

    weitere vorschläge sind natürlich stets wilkommen 😃



  • Welchen Compiler nutzt du? Weil je nach Compiler kannst du das Padding unterschiedlich ausstellen.

    Beim GCC geht das mit

    struct foo {
      char c;
    } __attribute__((packed));
    

    Schau einfach mal in das Handbuch zu deinem Compiler.



  • aoeu schrieb:

    hm es geht mir ja mehr ums schreiben von wave dateien

    Na und? Lesen, schreiben? Wo ist da der Unterschied?

    aoeu schrieb:

    und ich denke wenn ich da nicht sizeof(wheader) nehme kommt müll raus wenn die paddingbytes nicht am ende sind...

    Die Padding Bytes sind aber immer am Ende, ausser du verwendest verschachtelte Strukturen. Würde ich dir aber nicht empfehlen.



  • groovemaster schrieb:

    Die Padding Bytes sind aber immer am Ende, ausser du verwendest verschachtelte Strukturen. Würde ich dir aber nicht empfehlen.

    Das musst du mir erklären. Wieso sollte der Compiler nicht zum Beispiel in der Struktur ein Padding Byte einfügen, um damit die Daten besser an einer Word Grenze anzulegen. Zum Beispiel:

    struct Foo
    {
      short a; //offset 0
      char b; //offset 2
      //padding Byte
      int c; //offset 4
    };
    

    Es wäre hier doch aber Schwachsinn das Padding Byte am Ende anzufügen, oder?



  • Irgendwer schrieb:

    Das musst du mir erklären. Wieso sollte der Compiler nicht zum Beispiel in der Struktur ein Padding Byte einfügen, um damit die Daten besser an einer Word Grenze anzulegen.

    Ähh, weil wir hier vom Wave Header reden? 🙄
    Ansonsten hast du natürlich Recht.



  • kingruedi schrieb:

    struct foo {
      char c;
    } __attribute__((packed));
    

    bei den vielen anderen compilern heisst es

    #pragma pack(1) // an byte-grenzen packen
    

    btw: es wird nicht die struct am ende aufgebläht sondern die members werden erweitert, so dass z.b. jedes element der struct an einer durch 4 teilbaren adresse beginnt (default bei x86)



  • Du könntest deine padding bytes doch auch
    einfach selbst reinpacken 😉

    struct WaveHeader {
        // deine member ..
    
        static size_t getSize() {
            return 44;
        }
    
    private:
        char paddingBytes[4];
    };
    
    void f() {
        WaveHeader header;
    
        read(reinterpret_cast<char*>(&header), WaveHeader::getSize());
    }
    


  • net schrieb:

    so dass z.b. jedes element der struct an einer durch 4 teilbaren adresse beginnt (default bei x86)

    Das ist aber compilerspezifisch.

    net schrieb:

    btw: es wird nicht die struct am ende aufgebläht sondern die members werden erweitert

    Nochmal, wir reden hier vom Wave Header. Da gibt es keinen Grund, warum ein Compiler irgendwo mittendrin Padding Bytes einfügen sollte. Ausser aoeu hat hier ziemlich unvorteilhaft struktieriert.

    struct WAVE_HEADER
    {
        char riff[4];
        uint32 file_length;
        char wave[4];
        char fmt_[4];
        uint32 fmt_length;
        uint16 fmt_tag;
        uint16 channels;
        uint32 sample_rate;
        uint32 bytes_per_second;
        uint16 block_align;
        uint16 bits_per_sample;
        char data[4];
        uint32 data_length;
    }
    

    Wo sollen hier bitte Padding Bytes herkommen? (ich geh jetzt einfach mal von einem x86-32 System aus)
    Den wirklichen Grund der Padding Bytes kann man aber nur feststellen, wenn aoeu uns seine Struktur zeigt.


Anmelden zum Antworten