Irgendwie ist das heute nicht mein Tag... Bei der angefügten Maske geht der µC in die if-Anweisung obwohl an dieser Stelle gar keine "1" steht. Ich verstehs nicht was er hier tut. Evtl. kann sich das ja jemand iiirgendwie erklären. dada ist ein uint64_t zi ist ein uint8_t Welche Zahlen dort gerade drin stehen, hat das Atmel Studio drüber geschrieben. Momentan hängt er im Breakpoint der if.
tobi schrieb: > Welche Zahlen dort gerade drin stehen, hat das Atmel Studio drüber > geschrieben. Und diesen Dezimalzahlen soll man jetzt ansehen, ob das entsprechende Bit gesetzt ist? Sorry
tobi schrieb: > Evtl. kann sich das ja jemand iiirgendwie erklären. Tja, wenn man die Sprache beherrscht, dann weiß man, das Operatorpräzedenzen gibt. Und man weiß auch, daß man diese bei Bedarf durch geeignete Klammersetzung ändern kann. Oder anders ausgedrückt: Deine Bedingung tut nicht, was du glaubst, dass sie tut.
Hi c-hater schrieb: > Oder anders ausgedrückt: Deine Bedingung tut nicht, was du glaubst, dass > sie tut. Vielleicht solltest du noch dazuschreiben, das sie das tut, was sie lt. Hersteller tun soll Gruß oldmax
c-hater schrieb: > Deine Bedingung tut nicht, was du glaubst, dass sie tut. Sie tut nicht, was die Formatierung vermuten lässt. Sie hat es aber auch schon nicht getan, bevor zi=15 war... Korrekt formatiert sieht sie so aus:
1 | if ( dada&1 << zi ) |
2 | ...
|
Sieh dir das an: https://de.wikibooks.org/wiki/C-Programmierung:_Liste_der_Operatoren_nach_Priorit%C3%A4t Dort erkennst du, dass zuerst der & Operator berechnet wird, danach der << Operator... Forist schrieb: > Und diesen Dezimalzahlen soll man jetzt ansehen, ob das entsprechende > Bit gesetzt ist? Sorry Man kann sie umrechnen. Und wenn man das nicht tun will, dann lässt man die Antwort bleiben...
Lothar Miller schrieb: > Dort erkennst du, dass zuerst der & Operator berechnet wird, danach der > << Operator... Das ist richtig. Mit Klammern kann man den kompiler aber dazu bringen, trotzdem das zu tun, was man will :) Aber dennoch dürfte das Programm nicht in die if() springen, denn
1 | 0x964000 & 0x01 |
ist immer Null, egal wie weit man das rotiert.
Hi
ich bin zwar nicht mit der Schreibweise so sattelfest vertraut und schon
gar nicht mit der Sprache, aber...
Dez. 9846784 -> 100101100100000000000000
1<<15 -> 100000000000000
oder macht der Compiler nicht die 1 an die 15. Stelle? Denn dann ergibt
9846784 & 100000000000000 eine 1 und damit ist die If-Bedingung erfüllt.
Oder sehe ich das falsch?
Gruß oldmax
Little Basdart schrieb: > Das ist richtig. Mit Klammern kann man den kompiler aber dazu bringen, > trotzdem das zu tun, was man will :) > > Aber dennoch dürfte das Programm nicht in die if() springen, > denn0x964000 & 0x01 > ist immer Null, egal wie weit man das rotiert. Ich schließe mich der Verwunderung an.
Kann es sein, dass dada über einen Interrupt nach der If-Abfrage und dem Breakpoint verändert wurde? Ist dada in diesem Moment wirklich 9846784?
Lothar Miller schrieb: > Sieh dir das an: > https://de.wikibooks.org/wiki/C-Programmierung:_Liste_der_Operatoren_nach_Priorit%C3%A4t > Dort erkennst du, dass zuerst der & Operator berechnet wird, danach der > << Operator... Äh. Nein. << hat höhere Precedence als das & (und). Nicht mit dem Address-of Operator verwechseln.
Hier passiert ganz was anderes. in
1 | 1 << z1 |
ist die 1 vom Datentyp int. D.h. dieser Ausdruck wird auch in int gerechnet. Schiebt man ein 1 Bit aber bei einem 16 Bit int 15 mal nach links, dann wandert es an die Stelle, an der bei einem 16 Bit int das Vorzeichenbit bei 2-er Komplement sitzt. D.h. diese Operation erzeugt effektiv eine negative int Zahl. Wird diese negative int Zahl auf 64 Bit aufgeblasen, damit sie verundet werden kann, dann wird das Vorzeichenbit entsprechend erweitert: alle links angehängten Bytes sind 0xFF. Und damit bleibt bei der Verundung etwas übrig was nicht 0 ist.
1 | if( data & ( (uint64_t)1 << z1 ) ) |
Der Cast auf einen 64 Bit unsigned Typ ist sowieso notwendig. Denn spätestens wenn z1 größer als 15 geworden wäre, wäre sonst immer 0 rausgekommen (*) und die nächste Anfrage im Forum wäre fällig gewesen. Ein
1 | if( data & ( 1U << z1 ) ) |
wäre nicht ausreichend, wenn z1 größer als 15 werden kann, was man leider im Bild nicht sehen kann. Das man diese Shift Operation mit einem variablen Argument auf einem AVR nicht haben will, ist davon losgelöst eine ganz andere Geschichte. Edit: (*) Genau genommen ist es undefiniert, was dann rauskommt, wenn man über die Bitbreite des Datentyps rausschiebt.
Martin D. schrieb: > Ich schließe mich der Verwunderung an. Jetzt habe ich mir extra die Mühe gemacht und Karl-Hainz war wieder schneller. Egal. mfg.
Ui, danke der vielen Mitdenker. Schade, dass in der Frühe die Antworten immer so aggressiv ausfallen. Naja, wenn man die ersten drei ignoriert ist es ja dann doch gut das ich fragte ;) @Lothar: Jetzt hast Du mich geschockt :) Aber wurde ja ein paar Zeilen darunter wieder aufgeklärt. Klammersetzung hatte ich gestern/heute Nacht auch probiert. Das erbrachte aber leider keine Besserung. @Martin: Die Idee hatte ich auch kurz gehabt. "Leider" ist der Wert der Variable vor der if, wie auch in der if gleich geblieben. Auch ein Überschreiben des Speicherbereiches durch etwas falsch zugewiesenes ist ja damit eigentlich ausgeschlossen. @Karl Heinz: Vielen Dank auch an Dich für die tolle Erklärung und Verfechtung mit der Priorität zwischen "& / <<"! @Karl Heiz & Thomas: Wow, da muss man erst mal drauf kommen. Bin grade ausser Haus und werde das mit dem Casting später definitiv testen wenn ich daheim bin.
tobi schrieb: > @Lothar: Jetzt hast Du mich geschockt :) Aber wurde ja ein paar Zeilen > darunter wieder aufgeklärt. War ja noch früh am Morgen... :-/ Die Sache mit dem Integer hatte ich auch auf der Zunge, aber wegen der vielen ARM-Geschichten ist für mich ein Integer derzeit defaultmäßig 32 Bit breit, deshalb kann es beim Bit 15 noch keine Probleme geben... ;-) BTW: das dauernde Shiften ist auf dem AVR übrigens echt ineffizient (wie auch die Anwendunge eines 64 Bit Integers fraglich ist). Besser wäre es, du schiebst eine Maske:
1 | for ( uint32_t m = 1, zi=0; zi<15; m<<=1, zi++ ) { |
2 | if( data & m ) ... |
3 | }
|
Yesssss, es funktioniert :) Ist eigentlich auch logisch, dass dort her das Problem kam. Leider habe ich daran nicht gedacht - nächstes mal dran denken ;) Euch ein schönes Wochenende! Mit dem Masken schieben schaue ich mir nochmal an, danke dir.
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.

