einen INT byteweise vertauschen



  • Hallo,
    ich habe folgendes Problem,
    ich muss aus einer siemens Steuerung Daten auslesen. Dazu stellt Siemens ne dll bereit. Als Ergebnis bekomme ich einen Zeiger auf das anfang der Zahl so z.B

    int16  *value_array[1]; // int16 = SHORT INT
    s7_get_cycl_read_ind((void *)0,&result,&var_length, value_array);
    int16 a = *value_array[0];
    

    Nun zum Problem. In der Steuerung sind die Bytes vertauscht.
    zB. ist 38 als

    0000_0000_0010_0110
    

    dargestellt. Unter Windows bedeutet das natürlich

    0010_0110_0000_0000
    

    also 9728 😞

    Hat da jemand ne Idee, wie ich die Bytes tauschen könnte?



  • kleines Missgeschick von mir. Die beiden Binärdarstellungen sollten genau umgekehrt sein. Sorry

    Roman



  • Es gibt viele Möglichkeiten. Eine wäre:

    int16 val = ...; 
    val = (val << 8)|(val >> 8);
    

    Du könntest auch google nach little und big endian befragen.



  • Dein Code ist keine so gute Idee, weil val vorzeichenbehaftet ist. Der Ausdruck in der zweiten Zeile sollte lauten:

    (val << 8) | ((val >> 8) & 0xff)
    


  • Du könntest die Funktionen (oder je nach Impl. Makros) htons bzw. ntohs benutzen (Host- to Network-Byteorder - short], bzw. umgekehrt) benutzen, die diese Umwandlung je nach Plattform richtig für dich machen. Allerdings gibt's die in reinem C++ nicht, sondern werden Dir unter Windows z.B. von der Socketbibliothek zur Verfügung gestellt.



  • Roman007 schrieb:

    Hat da jemand ne Idee, wie ich die Bytes tauschen könnte?

    #include <algorithm>
    
        int value = 38;  // oder short oder long oder ...
        std::reverse( reinterpret_cast< char* >( &value ), reinterpret_cast< char* >( &value + 1 ) );
    

    Gruß
    Werner



  • oder so

    #include <algorithm>
    
    int value = 0x1133;  // oder short oder long oder ...
    std::swap(*(reinterpret_cast<char*>(&value)), *(reinterpret_cast<char*>(&value) + 1));
    


  • Redhead schrieb:

    oder so

    #include <algorithm>
    
    int value = 0x1133;  // oder short oder long oder ...
    std::swap(*(reinterpret_cast<char*>(&value)), *(reinterpret_cast<char*>(&value) + 1));
    

    hast Du das getestet? 🕶



  • jep(VC6), es macht
    0x1133 => 0x3311

    hoffe wir meinen/machen das Gleiche. 😃



  • Sehe ein das wir nicht GANZ das Gleiche tun. Hätte vielleicht vorher die "Original"-Aufgabe
    lesen sollen. 😃 😃 😃



  • Redhead schrieb:

    jep(VC6), es macht
    0x1133 => 0x3311

    hoffe wir meinen/machen das Gleiche. 😃

    vielleicht nicht.
    Ich hatte den OP so versstanden, die Reihenfolge aller (!) Bytes eines int-Wertes zu vertauschen. Dein Vorschlag vertauscht die ersten beiden Bytes im Memory unabhängig davon, aus wieviel Bytes der Ziel-Wert besteht (int i.A. 4 Bytes). Alle andere Bytes bleiben stehen.
    Wenn Du einen int (von 4 Bytes) vom Wert 0x1133 hast, so würde ich beim Vertauschen 0x33110000 erwarten.
    Bei int16-Werten funkt's natürlich auch mit swap.

    Gruß
    Werner



  • danke an alle. 🙂
    ich habe seit gestern keine Möglichkeit vorbeizuschauen.
    Es hat sich was getan, ich wusste gar nicht, dass es so einfach ist, die Bytes zu tauschen. Ich habe gleich die erste Methode gewählt, und die funzt schon.
    Das es bei jedem Datentyp läuft hab ich die Funktionen überladen

    void endian_swap(unsigned short& x) { x = (x>>8)| (x<<8); &0x00FF } 
    void endian_swap(unsigned int& x) { x = (x>>24) | ((x<<8) & 0x00FF0000) 
                                                    | ((x>>8) & 0x0000FF00) 
                                                    | (x<<24); } 
    inline void endian_swap(unsigned int64& x) { x = (x>>56) 
                                                | ((x<<40) & 0x00FF000000000000) 
                                                | ((x<<24) & 0x0000FF0000000000) 
                                                | ((x<<8)  & 0x000000FF00000000) 
                                                | ((x>>8)  & 0x00000000FF000000) 
                                                | ((x>>24) & 0x0000000000FF0000) 
                                                | ((x>>40) & 0x000000000000FF00) 
                                                | (x<<56); }
    

    Euere Lösungenen sehen aber einfacher aus, muss es ausprobieren

    Danke nochmal
    Roman


Anmelden zum Antworten