Forum: Mikrocontroller und Digitale Elektronik Binärzahlen und Abfrage einzelner Bits in C /


von Christoph Budelmann (Gast)


Lesenswert?

Hallo zusammen,

als C-Anfänger habe ich folgende, für die meisten von euch
wahrscheinlich ziemlich leicht zu beantwortende Fragen:

1. Wie kann ich einzelne Bits eines Zeichens abfragen? Es geht um eine
Manchestercodierung, bei der ich ein Daten-Byte habe, das dann in zwei
Manchester codierte Bytes umgewandelt wird. Hierfür müsste ich die
einzelnen Bits des Datenbytes auslesen.

2. Was mache ich falsch, wenn ich Binärzahlen in C verwenden will,
beispielsweise 0b1000000 eingebe und mir der Compiler dann sagt, dass
b10000000 eine ungültige Nachsilbe sei?

Gruß
Christoph

von crazy horse (Gast)


Lesenswert?

0bx gehört leider nicht zum C-Sprachumfang. Da es aber manchmal sehr
nützlich ist, unterstützen es einige Compiler.
Zur Abfrage einzelner Bits: dafür gibts mehrere Möglichkeiten.
Hier mal eine:
if (temp&0x80) // testet Bitstelle 7

von T.Stütz (Gast)


Lesenswert?

@Christoph Budelmann

Manche Compiler für uController kennen auch einen Datentyp "bit"
damit vielleicht ein
union {
bit bD0;
bit bD1;
...
} BitFeld;

@crazy horse
Ist vielleicht besser so zu schreiben:

if (0x00 != (temp & 0x80)) {
}

da
1. manche Compiler dann gleich einen jnbz / jbz erzeugen
2. manche (uralte) Compiler mit dem "BOOL"-Wert 0x80 nix anfangen
können
3. Der Kollege gerade anfängt und deswegen vielleicht diese Verkürzung
noch nicht kennt.
4. Ich habe mir es angewöhnt den Konstanten Teil links zu schreiben da
dadurch der Fehler "if (i=0) " (Zuweisung anstatt Abfrage) nicht
passieren kann (der Compiler sieht das dann als Fehler an)
5. Leerzeichen erhöhen die Üersichtlichkeit, auch wenn es Tipparbeit
ist

Bitte NICHT bös nehmen
Gruss T.Stütz

von crazy horse (Gast)


Lesenswert?

aus
if (test&0x80)...

macht mein Compiler:
sbrs r16,7
rjmp bit_7_ist_0
..

erkennt also, dass das eine reine Bitabfrage ist.
Und zur Schreibweise - da gibt es sehr viele persönliche Vorlieben,
jeder muss sehen, wie er am besten zurecht kommt.

von Chris (Gast)


Lesenswert?

@T.Stütz:

Zu 1.: aus if(test&0x80) sollte jeder halbwegs gescheite Compiler, der
aus dem Alpha-Stadium heraus ist, exakt denselben Code erzeugen wie aus
if(0 != (test&0x80)).
Zu 2.: Ist dir so ein Compiler schon mal untergekommen? Wenn ja,
welcher?
Zu 3.: Man sollte diese "Verkürzung" IMHO dann kennen, wenn man das
if-Statement lernt. Z.B. einen Test auf Nullpointer wird ja wohl
niemand, der seit mehr als ein paar Wochen C lernt, als if(p != 0)
schreiben. Man will schließlich testen, ob der Pointer gültig ist,
daher ist if(p) sogar semantisch viel einfacher zu verstehen.
Zu 4.: Nahezu jeder Compiler erzeugt bei if(i = 0) eine Warnung. Es sei
denn natürlich, man hat Warnungen abgeschaltet.
Zu 5.: Dem stimme ich zu. Allerdings besteht if(0x0 != (test & 0x80))
aus mehr als ein paar zusätzlichen Leerzeichen. Das 0x0 != sowie die
Klammern um den zweiten Term kann man getrost weglassen, ohne die
Übersicht zu verschlechtern. Sie wird sogar eher besser.


Ich nehm deine Aussagen nicht böse, nur solche Thesen sollten hier
nicht einfach so unkommentiert stehenbleiben.

von Peter D. (peda)


Lesenswert?

@Chris,

NULL muß nach C Standard nicht zwingend 0 sein, ist es aber meistens.

Ich hatte z.B. beim 8051 eine Routine, die nicht funktionierte, weil
dort 0 eine gültige Datenadresse ist und der Linker die Variable auch
dort abgelegt hatte. Da ich nun nicht den gesamten Quelltext (~50
Files) nach if(p) absuchen wollte, habe ich als Workaround dem Linker
gesagt, das der XDATA Bereich bei 0x0001 anfängt und dann ging es.

Die Schreibweise if(p != NULL) sollte man daher vorziehen.


Peter

von Chris (Gast)


Lesenswert?

> NULL muß nach C Standard nicht zwingend 0 sein, ist es aber meistens.

Das ist mir durchaus bekannt.
In diesem Zusammenhang ("if(p != 0)") spielt das allerdings nur eine
untergeordnete Rolle. 0 wird hier automatisch in den Null-Zeiger
konvertiert, egal ob er nun den Zahlenwert 0, 0xFF oder irgendwas
anderes aufweist. Entsprechendes gilt auch für if(p), das ja genau das
gleiche wie if(p != 0) darstellt.

Wenn ein Compiler diese Umwandlung (0 nach Null-Zeiger) nicht
automatisch erledigt, verletzt er AFAIK den ANSI-Standard.

von T.Stütz (Gast)


Lesenswert?

@crazy horse
Stimme ich zu

@Chris
zu1.) Deswegen habe ich auch "(uralt)" geschrieben
zu2.) PDOS, der Compiler hat sogar einen normalen Brief zu einer EXE
gemacht. Ausserdem Force Unix System V (das ist aber schon 15 Jahre
her)
zu3.) mit "if (p != 0)" vergleichst du einen konstanten Wert (int)
mit einem Zeiger, da muss eigentlich der Compiler eine Warning
ausspucken?
zu4.) Ja, eine Warnung wird (bei höchstem Warninglevel) ausgespuckt.
jedoch wird selbige gerne übersehen oder gemeinhin einfach ignoriert
zu5.) "if (0 != temp & 0x80)" => zuerst wird 0 != temp berechnet
danach das Ergebnis mit 80h verundet. Siehe auch K&R - C

und stimmt es sind ein paar Zeichen mehr
und stimmt ich hab da vielleicht etwas "überreagiert"
und sorry falls ich jetzt wieder jemand auf den Schlips getreten bin.

Grüße @all

von Chris (Gast)


Lesenswert?

> zu2.) PDOS, der Compiler hat sogar einen normalen Brief zu einer EXE
> gemacht. Ausserdem Force Unix System V (das ist aber schon 15 Jahre
> her)
Interesant. Ein if(0x80) hat bei diesen Compilern also zu fehlerhaftem
Verhalten geführt?
Leider (zum Glück?) bin ich so einen Compiler noch nicht begegnet.
Achso, du schreibst ja selbst, dass es schon anderthalb Jahrzehnte her
ist.
Heutige Compiler können das glücklicherweise durchweg (in dem Fall muss
man sich IMHO von Altlasten lösen).

> zu3.) mit "if (p != 0)" vergleichst du einen konstanten Wert (int)
> mit einem Zeiger, da muss eigentlich der Compiler eine Warning
> ausspucken?

Siehe mein letztes Posting. In diesem Kontext wird 0 von einem
ANSI-C-Compiler implizit in den Nullzeiger konvertiert.

> zu4.) Ja, eine Warnung wird (bei höchstem Warninglevel) ausgespuckt.

> jedoch wird selbige gerne übersehen oder gemeinhin einfach ignoriert

Warnungen sollte man IMHO niemals ignorieren, denn sie weisen auf
mögliche logische Fehler hin.
Wenn sie aus bestimmten Gründen nicht zu vermeiden sind (z.B. aufgrund
einer Compilereigenheit), kann man sie mit #pragma o.ä. selektiv
deaktiveren oder den Ausdruck entsprechend umschreiben.

> "if (0 != temp & 0x80)" => zuerst wird 0 != temp berechnet
> danach das Ergebnis mit 80h verundet. Siehe auch K&R - C
Ich meinte "sowie". Nur die Klammern weglassen kann man nicht, das
0x0 != muss dann ebenfalls weg.

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
Noch kein Account? Hier anmelden.