byte array in struktur



  • Ich habe eine TCP Verbindung und bekomme eine Menge Bytes zurück. Diese Bytes haben eine bestimmte Struktur. Nun dachte ich, man kann ein struct anlegen und den Pointer darauf verweisen. Aber so leicht scheint das nicht zu funktionieren.

    unsigned char buf[500];
    
    typedef struct {
        unsigned status : 8;
        unsigned dailylow : 5;
        unsigned datlyhigh : 5;
        unsigned counter : 4;
        unsigned crc : 2;
    } mydata;
    
    mydata dldata;  // Hier sollen die Daten rein
    

    Die Struktur ist nur ein Beispiel und noch viel länger. Jetzt funktioniert zwar die Angabe von

    dldata = &buf[0];
    

    aber das ist wohl nicht die feine Art. Wie macht man das richtig/schöner?

    Viele Grüße Ronny



  • Welche Struktur haben die Bytes? Die von dir gepostete? Das sieht mir so nach ekeligen Bitfields aus.
    Was sind das für Daten?



  • Ja genau so und weitere eklige bytes kommen da noch dazu. Deshalb in Bitweiser Struktur. Später kann ich die nötigsten Daten in ein vernünftige Struktur packen. Aber die Daten die ich bekomme sehen leider so bescheiden aus...



  • dldata = &buf[0];
    

    funzt schonmal nicht und dürfte nicht einmal kompilieren.

    Je nachdem, ob der Puffer Füllbytes mit überträgt, käme sowas hier in Frage:

    memcpy ( &dldata, buf, sizeof(mydata) );
    


  • hronny schrieb:

    Ich habe eine TCP Verbindung und bekomme eine Menge Bytes zurück. Diese Bytes haben eine bestimmte Struktur. Nun dachte ich, man kann ein struct anlegen und den Pointer darauf verweisen. Aber so leicht scheint das nicht zu funktionieren.

    das geht auch nicht gut, du musst die daten einzeln aus dem empfangsbuffer (nach protokollspezifikation) rauspflücken. einen struct-pointer drüberzulegen ist, wegen struct-padding und alignment, 'ne extrem wacklige sache. fall's du's hinbekommst, nagelst du dich damit ausserdem auf einen compiler fest. mach es also besser gleich portabel.
    🙂



  • Das memcpy funktioniert zwar, aber es stimmt wohl das aufgrund des struct-paddings nicht die passenden Werte rauskommen. Wie soll ich denn 5 einzelne bits aus einem Bytearray herrauspicken, wenn die Struktur quasi über 2 Bytes geht (also 3 Bits im ersten Byte und 2 Bits im nächsten)?
    Über den Kompiler mach ich mir eigentlich weniger Sorgen, es reicht wenn es mit gcc unter Linux übersetzt werden kann und funktioniert 😃



  • char x[2];
    ( ((x[0]&0x7)<<2) | ((x[1]&0xC0)>>6) )
    

    so?



  • allerdings gehts ach so:

    unsigned int start = 0xA6A6A6A6;//10100110 10100110 10100110 10100110
    unsigned int a = start & 0x15;
    start>>=4;
    unsigned int b = start & 0x7;
    start>>=3;
    unsigned int c = start & 0x1F;
    start>>=5;
    
    //a = 0110
    //b = 010
    //c = 01101
    

    man müßte das noch ausgiebig testen aber so in der richtung könnts auch klappen
    natürlich kannst du auch in die andere richtung shiften, allerdings war es mir jetzt zu prall da so große hex werte einzugeben;)

    lg lolo



  • hronny schrieb:

    Das memcpy funktioniert zwar, aber es stimmt wohl das aufgrund des struct-paddings nicht die passenden Werte rauskommen. Wie soll ich denn 5 einzelne bits aus einem Bytearray herrauspicken, wenn die Struktur quasi über 2 Bytes geht (also 3 Bits im ersten Byte und 2 Bits im nächsten)?

    Das Einfachste ist, Sender und Empfänger anzupassen. Möglicherweise ist die Struktur auf der Senderseite gepackt. Beim MSVC würde man sowas in der Art schreiben:

    #pragma pack(1)
    typedef struct {
        unsigned status : 8;
        unsigned dailylow : 5;
        unsigned datlyhigh : 5;
        unsigned counter : 4;
        unsigned crc : 2;
    } mydata;
    #pragma pack()
    

    Vergleiche sizeof(mydata) mit und ohne #pragma pack. Der gcc mag da seine eigene Syntax haben. So oder so, d.h. auch bei dem Bitshiftgefrickel musst tu wissen, wieviel Bytes die Strukturen haben, wenn davon mehrere auf einmal ankommen. ( Hier wären das ca. 4 Bytes ohne und 3 Bytes mit der #pragma Anweisung ).



  • Big Brother schrieb:

    Das Einfachste ist, Sender und Empfänger anzupassen.

    ^^nee, lasst das bleiben. structs sind nur innerhalb des codes gut, für jede form von I/O sind sind nicht zu gebrauchen bzw. machen ständig ärger.
    hronny: definiere dir ein protokoll, in dem genau feststeht, wo in dem paket jedes bit und byte zu sein hat (wenn du nicht sowieso schon eins hast). beim empfang lies byte-arrays ein und extrahiere die informationen daraus mit array-zugriffen, shifts und bitoperationen und beim senden konstruiere ebenfalls byte-arrays. kurz: finger weg von structs bei sowas.
    🙂



  • ;fricky schrieb:

    ^^nee, lasst das bleiben. structs sind nur innerhalb des codes gut, für jede form von I/O sind sind nicht zu gebrauchen bzw. machen ständig ärger.

    Und warum? Hier wären doch die Füllbytes nur am Ende des letzten Members (unsigned crc) zu erwarten, oder? Wenn ich weiß, das der Sender die Struktur genauso packt wie der Empfänger, wo gibt es dann ein Problem?



  • Big Brother schrieb:

    Wenn ich weiß, das der Sender die Struktur genauso packt wie der Empfänger, wo gibt es dann ein Problem?

    du bist dann z.b. auf's compilerspezifische packen angewiesen bist. z.b. kannste den code nicht einfach auf einen anderen compiler loslassen, optimierungs-optionen ändern usw. sogar beim update auf eine neue version des gleichen compilers kann's schiefgehen, usw. C-structs sind eine feine sache, solange sie sich im code befinden, aber zur kommunikation mit anderen systemen absolut ungeeignet. mit bitfields (siehe die struct des OP) wird das ganze nochmals besonders unlustig.
    🙂



  • Habs gerade nochmal getestet:

    #pragma pack(1)
    typedef struct {
        unsigned status : 8;
        unsigned dailylow : 5;
        unsigned datlyhigh : 5;
        unsigned counter : 4;
        unsigned crc : 2;
    } mydata;
    #pragma pack()
    

    sizeof(mydata) ergibt 4 und nicht 3, wie ich eigentlich erwartet hätte. 😮


Anmelden zum Antworten