Zwei 1 Byte Werte in einer 2 Byte Variable speichern



  • In der Regel ist es portabel auf den meisten Systemen, jedoch nicht 100 %.

    Zum einen, wird nicht bedacht, dass ein byte mehr als 8 bit haben kann (oder weniger), also ist ein shiften um 8 falsch. Du bedenkst außerdem nicht, dass ein short auch nur 1 byte groß sein kann, also passt deine Datenmenge gar nicht in den Typ. Zu guter letzt ignorierst du jeglichen Aspekt der Endianess, sodass deine Shift-Richtung falsch sein kann.

    Ein char ist übrigens definiert genau 1 byte groß. Nicht jedoch 8 bit.



  • Mir ist klar wie ich an den zweiten Wert komme:

    cout << (var >> 8);
    

    Aber wie komme ich an den ersten?



  • Binäre und-Verknüpfung.

    Google mal nach Binäroperationen.



  • Janjan schrieb:

    Zum einen, wird nicht bedacht, dass ein byte mehr als 8 bit haben kann (oder weniger), also ist ein shiften um 8 falsch.

    Dann versuchs mit int. int hat auf jeder Plattform mindestens 16 bits.
    Zum Kodiern und Dekodieren:

    int zusammenfuegen (char a, char b) {
       int c = a;
       return (c << 8) | b;
    }
    
    int trennen (int c, char &a, char &b) {
       a = (c >> 8) & 0xff;
       b = c & 0xff;
    }
    

    Ich habe es nicht getestet, aber ungefähr so sollte es klappen.


  • Mod

    Und char ist mindestens 8 Bit laut Standard. Darf aber natürlich länger sein.



  • SeppJ schrieb:

    Und char ist mindestens 8 Bit laut Standard. Darf aber natürlich länger sein.

    Ich verwende char so gut wie garnicht mehr. Außer für Zeichen bzw. Zeichenketten (char* oder const char*).



  • ShortIstMord schrieb:

    short var = 0;
    char  var1 = 100;
    char  var2 = 200;
    var = var1 | ( var2 << 8);
    

    Du musst hier darauf aufpassen, dass char ein vorzeichenbehafteter Typ sein kann. Bei vorzeichenbehafteten 8bit-chars kann die Zahl 200 nicht dargestellt werden. Der Wert von var2 wäre dann implementierungsabhängig. Eine Reinterpretation der unteren 8 Bits angenommen, würde var2 den Wert -56 speichern. Bevor die Bitoperationen (<<, |) angewendet werden, findet eine "integral promotion" statt. Das heißt, var1 und var2 werden zu zwei int-Werten konvertiert. Auf der Linken Seite von << steht ein potentiell negativer Wert. Bitoperationen (inklusive <<) auf negativen Zahlen ist wieder implementierungsabhängig....

    Also, wenn Du Glück hast, passiert genau das, was Du willst. Das ist aber nicht garantiert.

    Guck mal hier: http://jk-technology.com/c/inttypes.html



  • krümelkacker schrieb:

    Bei vorzeichenbehafteten 8bit-chars kann die Zahl 200 nicht dargestellt werden. Der Wert von var2 wäre dann implementierungsabhängig. Eine Reinterpretation der unteren 8 Bits angenommen, würde var2 den Wert -56 speichern.

    Genauer: "unter der Annahme des Zweierkomplements und der Reinterpretation der Bits". Das Zweierkomplement ist zwar sehr populär, aber nicht vom C++ Standard vorgeschrieben.



  • Janjan schrieb:

    Zu guter letzt ignorierst du jeglichen Aspekt der Endianess, sodass deine Shift-Richtung falsch sein kann.

    Selten so einen Unfug gelesen...



  • Tim schrieb:

    Janjan schrieb:

    Zu guter letzt ignorierst du jeglichen Aspekt der Endianess, sodass deine Shift-Richtung falsch sein kann.

    Selten so einen Unfug gelesen...

    Ja sicher... Hast du noch nie das Problem gehabt, dass die Beispiele
    in den Bücher mit Shiften anstelle einer Multiplikation mit
    2^n nicht funktionierten, weil die Endianess nicht berücksichtigt wurde... 🙄



  • Braun-Bär Bruno schrieb:

    Tim schrieb:

    Janjan schrieb:

    Zu guter letzt ignorierst du jeglichen Aspekt der Endianess, sodass deine Shift-Richtung falsch sein kann.

    Selten so einen Unfug gelesen...

    Ja sicher... Hast du noch nie das Problem gehabt, dass die Beispiele
    in den Bücher mit Shiften anstelle einer Multiplikation mit
    2^n nicht funktionierten, weil die Endianess nicht berücksichtigt wurde...

    Nein, Tim hat recht. Ein links-shift um 1 entspricht immer einer Multiplikation mit 2. Das gilt für alle ganzzahligen Typen (char, short, int, long, ...) und deren vorzeichenlose Verwandten. Es spielt absolut keine Rolle, in welcher Reihenfolge die Bytes gespeichert werden.



  • Z schrieb:

    Nein, Tim hat recht. Ein links-shift um 1 entspricht immer einer Multiplikation mit 2. Das gilt für alle ganzzahligen Typen (char, short, int, long, ...) und deren vorzeichenlose Verwandten.

    1. Shifts auf negativen Zahlen sind implementierungsabhängig.
    2. Du tust so, als sei char vorzeichenbehaftet. char kann aber auch vorzeichenlos sein. Du weißt, dass es 3 char-Typen gibt, ja? char, signed char und unsigned char. Ob sich char sowie signed char oder wie unsigned char "verhält" (wertebereichstechnisch) ist nicht festgelegt.



  • short x;
    char a=56,b=199;
    char* p = (char*) &x;
    x[0]=a;
    x[1]=b;
    

    Ohne Garantie 😉 *scnr*



  • krümelkacker schrieb:

    Z schrieb:

    Nein, Tim hat recht. Ein links-shift um 1 entspricht immer einer Multiplikation mit 2. Das gilt für alle ganzzahligen Typen (char, short, int, long, ...) und deren vorzeichenlose Verwandten.

    1. Shifts auf negativen Zahlen sind implementierungsabhängig.
    2. Du tust so, als sei char vorzeichenbehaftet. char kann aber auch vorzeichenlos sein. Du weißt, dass es 3 char-Typen gibt, ja? char, signed char und unsigned char. Ob sich char sowie signed char oder wie unsigned char "verhält" (wertebereichstechnisch) ist nicht festgelegt.

    Probier mal das mit allen Compilern, die Dir zur Verfügung stehen:

    int main()  {
       char a = -3;
       signed char b = -3;
       unsigned char c = 3;
       printf ("%d %d %d\n", a<<1, b<<1, c<<1);  
    }
    

    Du bekommst immer -6, -6 und 6. Wollen wir wetten? 😉



  • Sorry...

    Hab wohl den falschen Smilie genommen...
    Das sollte ironisch sein...



  • Braun-Bär Bruno schrieb:

    Hab wohl den falschen Smilie genommen...
    Das sollte ironisch sein...

    Natürlich. Und der Text sollte eigentlich ein Geburtstagsgruß an Deine Großmutter werden. 😃



  • Braun-Bär Bruno schrieb:

    Sorry...

    Hab wohl den falschen Smilie genommen...
    Das sollte ironisch sein...

    Keine Sorge, ich habs so verstanden 🙂



  • Z schrieb:

    krümelkacker schrieb:

    Z schrieb:

    Nein, Tim hat recht. Ein links-shift um 1 entspricht immer einer Multiplikation mit 2. Das gilt für alle ganzzahligen Typen (char, short, int, long, ...) und deren vorzeichenlose Verwandten.

    1. Shifts auf negativen Zahlen sind implementierungsabhängig.
    2. Du tust so, als sei char vorzeichenbehaftet. char kann aber auch vorzeichenlos sein. Du weißt, dass es 3 char-Typen gibt, ja? char, signed char und unsigned char. Ob sich char sowie signed char oder wie unsigned char "verhält" (wertebereichstechnisch) ist nicht festgelegt.

    Probier mal das mit allen Compilern, die Dir zur Verfügung stehen:

    int main()  {
       char a = -3;
       signed char b = -3;
       unsigned char c = 3;
       printf ("%d %d %d\n", a<<1, b<<1, c<<1);  
    }
    

    Du bekommst immer -6, -6 und 6. Wollen wir wetten? 😉

    Sprich doch einfach aus, worauf Du hinaus willst. Ich halte es für wichtig, darauf hinzuweisen, was der Sprachstandard garantiert und was er nicht garantiert. Er garantiert nicht, dass char vorzeichenbehaftet ist. Er garantiert nicht, dass (-3<<1)==(-6) gilt. Er garantiert (noch) nicht, dass (-7/2)==(-3) gilt. Er garantiert nicht, dass (-1|2)==(-1) gilt, etc etc etc. Du bist scheinbar der Meinung, dass das nicht erwähnenswert ist.



  • krümelkacker schrieb:

    Ich halte es für wichtig, darauf hinzuweisen, was der Sprachstandard garantiert und was er nicht garantiert. Er garantiert nicht, dass char vorzeichenbehaftet ist. Er garantiert nicht, dass (-3<<1)==(-6) gilt.

    Ich denke schon, daß der Standard (-3)<<1 == -6 garantiert, sofern diese -3 ein Integer-Typ ist.
    Ich verwende C++ schon seit vielen Jahren und bisher bin ich von dieser wunderbaren Programmiersprache noch nicht enttäuscht worden. 😉



  • Z schrieb:

    krümelkacker schrieb:

    Ich halte es für wichtig, darauf hinzuweisen, was der Sprachstandard garantiert und was er nicht garantiert. Er garantiert nicht, dass char vorzeichenbehaftet ist. Er garantiert nicht, dass (-3<<1)==(-6) gilt.

    Ich denke schon, daß der Standard (-3)<<1 == -6 garantiert, sofern diese -3 ein Integer-Typ ist. Ich verwende C++ schon seit vielen Jahren und bisher bin ich von dieser wunderbaren Programmiersprache noch nicht enttäuscht worden.

    Und genau deswegen halte ich es für wichtig darauf hinzuweisen. Viele -- wie anscheinend Du auch -- gehen davon aus, dass dieses Verhalten garantiert ist.

    Im Entwurf des C++ Standards von 2005 kann man nachlesen:

    Shift Operators, §5.8/2-3:

    The value of E1 << E2 is E1 (interpreted as a bit pattern) left-shifted E2 bit positions; vacated bits are zero-filled. If E1 has an unsigned type, the value of the result is E1 multiplied by the quantity 2 raised to the power E2, reduced modulo ULONG_MAX+1 if E1 has type unsigned long, UINT_MAX+1 otherwise. [ Note: the constants ULONG_MAX and UINT_MAX are defined in the header <climits>. — end note ]

    The value of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 divided by the quantity raised to the power E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.

    implementation-defined behavior, §1.3.6:

    behavior, for a well-formed program construct and correct data, that depends on the implementation and that each implementation documents.

    Fundamental types, §3.9.1/1,7:

    [...] It is implementation-defined whether a char object can hold negative values. [...]

    [...] The representations of integral types shall define values by use of a pure binary numeration system. [ Example: this International Standard permits 2’s complement, 1’s complement and signed magnitude representations for integral types. — end example ]

    ==>

    |      -3      |   -3 << 1
    --------+--------------+------------------
    2's cmp | 111...111101 | 111...111010 (-6)
    1's cmp | 111...111100 | 111...111000 (-7)
    sgn+mag | 100...000011 | 000...000110 ( 6)
    

    Q.E.D.


Anmelden zum Antworten