5 Stimmen

Einige zufällige C-Fragen (ascii-Magie und bitweise Operatoren)

Ich versuche, die C-Programmierung zu erlernen, und ich habe einige Quellcodes studiert, und es gibt einige Dinge, die ich nicht verstanden habe, insbesondere in Bezug auf Bitwise-Operatoren. Ich habe einige Seiten dazu gelesen und irgendwie eine Vorstellung davon bekommen, was sie tun, aber als ich zurückging, um mir diese Codes anzusehen, konnte ich nicht verstehen, warum und wie sie verwendet wurden.

Meine erste Frage bezieht sich nicht auf die bitweisen Operatoren, sondern auf einige Ascii-Zaubereien:

  1. Kann mir jemand erklären, wie der folgende Code funktioniert?

    char a = 3;
    int x = a - '0';

    Ich verstehe, dass dies getan wird, um ein Char in ein Int zu konvertieren, aber ich verstehe die Logik dahinter nicht. Warum/Wie funktioniert das?

  2. Was nun die Bitwise-Operatoren betrifft, so fühle ich mich hier wirklich verloren.

    • Was bewirkt dieser Code?

      if (~pointer->intX & (1 << i)) { c++; n = i; }

      Ich habe irgendwo gelesen, dass ~ Bits invertiert, aber mir ist nicht klar, was diese Anweisung tut und warum sie das tut.

      Dasselbe gilt für diese Zeile:

      row.data = ~(1 << i);
    • Andere Frage:

      if (x != a)
        {
          ret |= ROW;
        }

      Was genau bewirkt der Operator |=? Von dem, was ich gelesen habe, ist |= OR, aber ich verstehe nicht ganz, was ist diese Anweisung tun.

      Gibt es eine Möglichkeit, diesen Code so umzuschreiben, dass er leichter zu verstehen ist und nicht diese bitweisen Operatoren verwendet? Ich finde sie sehr verwirrend zu verstehen, daher hoffe ich, dass mich jemand in die richtige Richtung weist, um zu verstehen, wie sie besser funktionieren!


Ich habe jetzt ein viel besseres Verständnis für bitweise Operatoren und der ganze Code macht jetzt viel mehr Sinn.

Eine letzte Sache: Anscheinend hat niemand geantwortet, ob es einen "saubereren" Weg gibt, diesen Code so umzuschreiben, dass er leichter zu verstehen ist und vielleicht nicht auf "Bit-Ebene". Irgendwelche Ideen?

0voto

Mark Ransom Punkte 283960

Ich denke, Sie haben sich wahrscheinlich vertippt und meinten:

char a = '3';

Der Grund dafür ist, dass alle Zahlen in der richtigen Reihenfolge stehen, und die "0" ist die erste. Offensichtlich ist '0' - '0' = 0. '1' - '0' = 1, da der Zeichenwert für '1' um eins größer ist als der Zeichenwert für '0'. Etc.

0voto

Sparr Punkte 7347

1) Ein char ist eigentlich nur eine 8-Bit-Ganzzahl. 0' == 48, und alles, was das bedeutet.

2) (~(pointer->intX) & (1 << i)) wertet aus, ob das 'i'te Bit (von rechts) im intX-Mitglied des Zeigers nicht gesetzt ist. Die ~ invertiert die Bits, so dass alle 0s zu 1s werden und umgekehrt, dann setzt die 1 << i eine einzelne 1 an die gewünschte Stelle, & kombiniert die beiden Werte, so dass nur das gewünschte Bit erhalten bleibt, und das Ganze wird zu true ausgewertet, wenn dieses Bit zu Beginn 0 war.

3) | ist bitweise oder. Es nimmt jedes Bit in beiden Operanden und führt eine logische ODER-Verknüpfung durch, die ein Ergebnis liefert, bei dem jedes Bit gesetzt ist, wenn bei einem der beiden Operanden dieses Bit gesetzt war. 0b11000000 | 0b00000011 == 0b11000011. |= ist ein Zuweisungsoperator, so wie a+=b a=a+b bedeutet, bedeutet a|=b a=a|b.

Der Verzicht auf bitweise Operatoren KANN in manchen Fällen die Lesbarkeit erleichtern, macht aber in der Regel auch den Code ohne starke Compiler-Optimierung deutlich langsamer.

0voto

mwigdahl Punkte 15620

Der Subtraktionstrick, auf den Sie sich beziehen, funktioniert, weil ASCII-Zahlen in aufsteigender Reihenfolge angeordnet sind, beginnend mit Null. Wenn also die ASCII-Zahl "0" ein Wert von 48 ist (und das ist sie), dann ist "1" ein Wert von 49, "2" ist 50, usw. Daher ist ASCII('1') - ASCII('0') = 49 - 48 = 1.

Mit den bitweisen Operatoren können Sie Operationen auf Bitebene mit Variablen durchführen.

Lassen Sie uns Ihr Beispiel aufschlüsseln:

(1 << i) -- Dies ist eine Linksverschiebung der Konstante 1 um i Bits. Wenn also i=0 ist, ist das Ergebnis dezimal 1. Ist i = 1, wird das Bit um eins nach links verschoben und mit Nullen aufgefüllt. Das Ergebnis ist binär 0010, also dezimal 2. Ist i = 2, wird das Bit um zwei Bits nach links verschoben und mit Nullen aufgefüllt, was binär 0100 oder dezimal 4 ergibt, usw.

~pointer->intX -- nimmt den Wert des intX-Mitglieds von pointer und invertiert seine Bits, indem alle Nullen in Einsen umgewandelt werden und umgekehrt.

& -- der Ampersand-Operator führt einen bitweisen AND-Vergleich durch. Das Ergebnis ist immer dann 1, wenn sowohl die linke als auch die rechte Seite des Ausdrucks 1 ist, und ansonsten 0.

Der Test ist also erfolgreich, wenn pointer->intX hat an der i-ten Stelle von rechts ein 0-Bit.

También, |= bedeutet, einen bitweisen ODER-Vergleich durchzuführen und das Ergebnis der linken Seite des Ausdrucks zuzuweisen. Das Ergebnis einer bitweisen ODER-Verknüpfung ist 1 für jedes Bit, bei dem das entsprechende Bit auf der linken oder rechten Seite 1 ist,

0voto

erik Punkte 3900

1) Kann mir jemand erklären, wie der folgende Code funktioniert? char a = 3; int x = a - '0'; Ich verstehe, dass dies getan wird, um ein char in einen int umzuwandeln, aber ich verstehe die Logik dahinter nicht. Warum/Wie funktioniert das?

Sicher. variabel a ist vom Typ char, und durch das Setzen von einfachen Anführungszeichen um die 0 wird sie von C ebenfalls als char angesehen. Schließlich wird die gesamte Anweisung automatisch in ihr Integer-Äquivalent typisiert, da x ist als ganze Zahl definiert.

2) Was die Bitwise-Operatoren betrifft, so fühle ich mich hier wirklich verloren. --- Was macht dieser Code? if (~pointer->intX & (1 << i)) { c++; n = i; } Ich habe irgendwo gelesen, dass ~ Bits invertiert, aber mir ist nicht klar, was diese Anweisung tut und warum sie das tut.

(~pointer->intX & (1 << i)) is saying:

intX negieren und mit einer um i Bits nach links verschobenen 1 UND verknüpfen

Wenn also intX = 1011 und i = 2 ist, ergibt sich folgendes Bild

(0100 & 0100) 

-negate 1011 = 0100

-(1 << 2) = 0100

0100 & 0100 = 1 :)

Wenn dann die UND-Verknüpfung eine 1 ergibt (was in meinem Beispiel der Fall ist) { c++; n = i; }

also c um 1 zu erhöhen und die Variable n auf i zu setzen

Dasselbe gilt für diese Zeile: row.data = ~(1 << i);

Same principle here.
Shift a 1 to the left by i places, and negate.

So, if i = 2 again

(1 << 2) = 0100

~(0100) = 1011

**--- Andere Frage:

if (x != a) { ret |= ROW; }

Was genau bewirkt der Operator |=? Nach dem, was ich gelesen habe, ist |= eine ODER-Verknüpfung, aber ich verstehe nicht ganz, was diese Anweisung bewirkt.

if (x != a) (hoffentlich ist dies für Sie ersichtlich....wenn Variable x nicht gleich Variable a ist)

ret |= ROW;

equates to

ret = ret | ROW;

das heißt, binäres ODER ret mit ROW

Um zu verstehen, was AND- und OR-Verknüpfungen genau bewirken, sollten Sie ein gutes Verständnis der binären Logik haben.

Siehe Wikipedia für Wahrheitstabellen...d.h.

Bitweise Operationen

0voto

  1. Ich nehme an, Sie meinen char a='3'; für die erste Zeile des Codes (andernfalls erhalten Sie eine ziemlich seltsame Antwort). Das Grundprinzip ist, dass ASCII-Codes für Ziffern fortlaufend sind, d.h. der Code für '0'=48, der Code für '1'=49, und so weiter. Durch Subtraktion der '0' wird der ASCII-Code einfach in die tatsächliche Ziffer umgewandelt, also z. B. '3' - '0' = 3 usw. Beachten Sie, dass dies nur funktioniert, wenn das Zeichen, von dem Sie die '0' abziehen, eine tatsächliche Ziffer ist - andernfalls hat das Ergebnis wenig Bedeutung.

  2. a. Ohne Kontext ist das "Warum" dieses Codes unmöglich zu sagen. Es scheint, dass die if-Anweisung als wahr ausgewertet wird, wenn das Bit i von pointer->intX nicht gesetzt ist, d.h. wenn dieses bestimmte Bit eine 0 ist. Ich glaube, dass der &-Operator vor dem ~-Operator ausgeführt wird, da der ~-Operator eine sehr niedrige Priorität hat. Der Code könnte die Klammern besser verwenden, um die beabsichtigte Reihenfolge der Operationen zu verdeutlichen. In diesem Fall dürfte die Reihenfolge der Operationen jedoch keine Rolle spielen - ich glaube, das Ergebnis ist in beiden Fällen dasselbe.

    b. Damit wird einfach eine Zahl erzeugt, bei der alle Bits mit Ausnahme von Bit i auf 1 gesetzt sind. Eine bequeme Möglichkeit, eine Maske für Bit i zu erstellen, ist die Verwendung des Ausdrucks (1<<i).

  3. Die bitweise ODER-Verknüpfung wird in diesem Fall verwendet, um die durch die ROW-Konstante angegebenen Bits auf 1 zu setzen. Wenn diese Bits nicht gesetzt sind, werden sie gesetzt; wenn sie bereits gesetzt sind, hat dies keine Auswirkungen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X