Bit-Maskieren detektiert eine 0 als 1

Gast #4170378
Lesenswert?
• ▲
▼
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.
Angehängte Dateien:
Gast #4170399
Lesenswert?
• ▲
▼
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.
Moderator (Firma: Titel) Persönliche Seite #4170436
Lesenswert?
• ▲
▼
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...
Gast #4170525
Lesenswert?
• ▲
▼
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
Gast #4170539
Lesenswert?
• ▲
▼
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.
#4170587
Lesenswert?
• ▲
▼
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.
Gast #4170691
Lesenswert?
• ▲
▼
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.
Moderator (Firma: Titel) Persönliche Seite #4170714
Lesenswert?
• ▲
▼
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
  }
Gast #4171410
Lesenswert?
• ▲
▼
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.

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.