Guten Morgen, vermutlich sehr einfache Frage. Ich habe folgendes Array: unsigned char Array[3]; Jetzt möchte ich gerne das letzte Bit rausschieben. Array = Array >> 1 funktioniert natürlich nicht. Am allerliebsten würde ich die drei Array Elemente als eine Zahl in einem int abspeicher, also Array[0] = High Byte, Array[1] = MittelByte, Array[2] = Low Byte, Dann könnte ich das letzte Bit auch einfach rausscheiben. Wie macht man sowas?
Spezi schrieb: > Guten Morgen, > > vermutlich sehr einfache Frage. > Ich habe folgendes Array: > > unsigned char Array[3]; > > Jetzt möchte ich gerne das letzte Bit rausschieben. > Array = Array >> 1 funktioniert natürlich nicht. > > Am allerliebsten würde ich die drei Array Elemente als eine Zahl in > einem int abspeicher, also Array[0] = High Byte, Array[1] = MittelByte, > Array[2] = Low Byte, > > Dann könnte ich das letzte Bit auch einfach rausscheiben. > > Wie macht man sowas? Entweder in dem man im Array schiebt
1 | uint8_t Carry1, Carry2; |
2 | |
3 | Carry1 = Array[2] & 0x01; |
4 | Array[2] >>= 1; |
5 | |
6 | Carry2 = Array[1] & 0x01; |
7 | Array[1] >>= 1 |
8 | if( Carry1 ) |
9 | Array[2] |= 0x80 |
10 | |
11 | Array[0] >>= 1; |
12 | if( Carry1 ) |
13 | Array[0] |= 0x80; |
oder den Compiler machen lassen, so wie du das vorgeschlagen hast.
1 | union convert |
2 | {
|
3 | uint8_t Bytes[4]; |
4 | uint32_t Value; |
5 | } convertVar; |
6 | |
7 | convertVar.Bytes[0] = Array[0]; |
8 | convertVar.Bytes[1] = Array[1]; |
9 | convertVar.Bytes[2] = Array[2]; |
10 | convertVar.Bytes[3] = 0; |
11 | |
12 | covertVar.Value >>= 1; |
13 | |
14 | Array[0] = convertVar.Bytes[0]; |
15 | ....
|
eine andere Möglichkeit, bei der man nicht umkopiert
1 | uint32_t * pValue; |
2 | |
3 | pValue = (uint32_t*)Array; |
4 | *pValue >>= 1; |
bei der Union Lösung hat man den Vorteil, dass man während des Umkopierens gleich die Bytereihenfolge für einen unsigned long entsprechend den Vorstellungen des COmpilers und/oder Systems anpassen kann, falls das notwendig ist. Bei der Pointer Variante muss man mit dem leben, wie sich der Compiler die Anordnung eines 32 Bit Wertes im Speicher so vorstellt. Oder aber: man findet einen Weg, wie man sich das ganze Bitgeschubse sparen kann. Normalerweise ist das der beste Ansatz.
Du könntest eine union verwenden:
1 | typedef union _Zahl_def{ |
2 | UCHAR Array[4]; |
3 | UINT32 Wert; |
4 | } Zahl_def; |
5 | |
6 | Zahl_def Zahl; |
7 | |
8 | Zahl.Array[0] = LowByte; |
9 | Zahl.Array[1] = MittelByte; |
10 | Zahl.Array[2] = HighByte; |
11 | Zahl.Array[3] = 0; |
12 | |
13 | Zahl.Wert = Zahl.Wert >> 1; |
Das ist jetzt aber ungeprüft. Edit: Da war einer schneller...
Vielen Dank schon einmal für die ausführlichen freundlichen Antworten: DIe Union Methode würde mich am Meisten interessieren: Bis convertVar.Bytes[0] = Array[0]; convertVar.Bytes[1] = Array[1]; convertVar.Bytes[2] = Array[2]; convertVar.Bytes[3] = 0; ist auch alles klar. Was genau macht er jetzt bei covertVar.Value >>= 1; ??? Klar shiftet er hier das Bit. In meiner Anwendung soll in Value doch nur 24 Bit stehen. Es müßte also in etwa wie folgt aussehen:
1 | union convert |
2 | {
|
3 | uint8_t Bytes[3]; |
4 | uint32_t Value; |
5 | } convertVar; |
6 | |
7 | convertVar.Bytes[0] = Array[0]; |
8 | convertVar.Bytes[1] = Array[1]; |
9 | convertVar.Bytes[2] = Array[2]; |
10 | |
11 | covertVar.Value >>= 1; |
In Value stehen jetzt leider (verständlicherweise) nicht wie gewünscht die 24 Bit.
Spezi schrieb: > OK ich muss einfach die 8 Nullen nochmal rausshiften ? Du musst da nichts rausshiften. Du schreibst 3 Bytes in die union (und initialisierst das 4.te mit 0) und holst dir 3 Bytes aus der union. Das in der union das Array 4 Bytes gross ist, hängt damit zusammen, dass auch ein uint32_t 4 Bytes gross ist und wir auch die Kontrolle über dieses 4.te Byte haben wollen. Und sei es nur, um es 0 zu setzen. Was natürlich sein kann: dass die Bytereihenfolge des Arrays nicht mit der in einem uint32_t übereinstimmt. Das muss man dann eben ausprobieren, wie rum ein uint32_t im Speicher angeordnet ist.
Karl Heinz schrieb: > eine andere Möglichkeit, bei der man nicht umkopiert >
1 | > uint32_t * pValue; |
2 | >
|
3 | > pValue = (uint32_t*)Array; |
4 | > *pValue >>= 1; |
5 | >
|
Das da noch keiner drauf angesprungen ist :-) Das ist natürlich so erst mal ungeheurer Blödsinn, solange das Array nur 3 Bytes gross ist.
Spezi schrieb: > In meiner Anwendung soll in Value doch nur 24 Bit stehen. Es gibt aber auf dem AVR keinen Standard Datentyp mit 24 Bit. Der nächst größere hat 32 Bit. Wenn du also dem Compiler die Arbeit aufbürden willst, das byteübergreifende Schieben für dich zu erledigen, dann wirst du dich wohl oder übel nach dem richten müssen, was du hast. Und nicht nach dem, was du gerne hättest. > Es müßte also in etwa wie folgt aussehen: > >
1 | > union convert |
2 | > { |
3 | > uint8_t Bytes[3]; |
4 | > uint32_t Value; |
5 | > } convertVar; |
6 | >
|
7 | > convertVar.Bytes[0] = Array[0]; |
8 | > convertVar.Bytes[1] = Array[1]; |
9 | > convertVar.Bytes[2] = Array[2]; |
10 | >
|
11 | > covertVar.Value >>= 1; |
12 | >
|
Frage: welchen Wert hat das Bit, welches von links (von seiten des MSB) reinkommt? Eben. Du hast da erst mal keine Kontrolle drüber. Daher: das Array 4 Bytes gross machen und dieses 4.te Byte (aus dem das 1 Bit nachgeschoben wird) auf 0 setzen.
Man kann auch 3 * 8 Bit schieben:
1 | void out24bit( uint8_t *array ) |
2 | {
|
3 | for( uint8_t i = 3; i; i-- ){ |
4 | uint8_t val = *array++; |
5 | for( uint8_t j = 8; j; j-- ){ |
6 | if( val & 1 ){ |
7 | mache_irgendwas(); |
8 | }
|
9 | val >>= 1; |
10 | }
|
11 | }
|
12 | }
|
Vielen Dank nochmal, es gilt also einfach die Reihenfolge zu überprüfen. Ich habe es jetzt fälschlicherweise wie folgt angeordnet: HB | MB | LB | 0 habe dann 1 Bit geshiftet und dann nochmal 8 Bit für die 0, was natürlich quatsch ist , wenn ich von Anfang an wie folgt anordne: 0 | HB | MB | LB Danke nochmals für die Hilfe. Was mich mal interessieren würde Herr Buchegg, machen Sie das ganze hier eientlich "vollberuflich"?
Spezi schrieb: > Was mich mal interessieren würde Herr Buchegg, machen Sie das ganze hier > eientlich "vollberuflich"? Manchmal kommt einem das so vor, gell?
Spezi schrieb: > Was mich mal interessieren würde Herr Buchegg, machen Sie das ganze hier > eientlich "vollberuflich"? Nein. Nebenbei, zwischen Compilerläufen.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.