Binäre Operationen

Schnelle objektorientierte, kompilierende Programmiersprache.
Antworten
Xeon
Beiträge: 41
Registriert: So Dez 17, 2017 4:10 pm

Binäre Operationen

Beitrag von Xeon » Mi Feb 05, 2020 2:55 pm

Hallo zusammen

Hier das Thema: https://www.proggen.org/doku.php?id=c:article:binaryops

Diese Aufgabe verstehe ich nicht:

Schreibe eine Funktion, die Dir die sechs Flags als Bitmuster ausgibt, also z.B. „011001“ für WINDOWFLAG_CLOSEBUTTON, WINDOWFLAG_FULLSCREEN und WINDOWFLAG_ALWAYSONTOP.

Code: Alles auswählen

flags = WINDOWFLAG_CLOSEBUTTON | WINDOWFLAG_BORDERLESS | WINDOWFLAG_RESIZEABLE |
           WINDOWFLAG_FULLSCREEN | WINDOWFLAG_ALWAYSONTOP | WINDOWFLAG_STATICPOSITION;
So währe doch jetzt das Bitmuster in flags oder?

nufan
Wiki-Moderator
Beiträge: 2459
Registriert: Sa Jul 05, 2008 3:21 pm

Re: Binäre Operationen

Beitrag von nufan » Mi Feb 05, 2020 3:02 pm

Hallo!
Der von dir gezeigte Code weist die kombinierten Flags einer Variable zu. Ziel der Aufgabe ist es nun, das dadurch entstandene Bitmuster (also in diesem Beispiel "011001") als Text auszugeben.

Xeon
Beiträge: 41
Registriert: So Dez 17, 2017 4:10 pm

Re: Binäre Operationen

Beitrag von Xeon » Mi Feb 05, 2020 3:57 pm

Aufgabe gelöst? :|

Code: Alles auswählen

void bitmuster_print(void)
{
    int muster;

    muster = WINDOWFLAG_CLOSEBUTTON | WINDOWFLAG_RESIZEABLE;
    if(muster & WINDOWFLAG_RESIZEABLE)
        printf("1");
    else
        printf("0");
    if(muster & WINDOWFLAG_BORDERLESS)
        printf("1");
    else
        printf("0");
    if(muster & WINDOWFLAG_CLOSEBUTTON)
        printf("1");
    else
        printf("0");

}

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8531
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Binäre Operationen

Beitrag von Xin » Mi Feb 05, 2020 4:09 pm

Xeon hat geschrieben:
Mi Feb 05, 2020 3:57 pm
Aufgabe gelöst? :|
Prinzipiell ja, ansonsten so ziemlich. :-)

Ich gehe davon aus, dass die Flags aus dem Text übernommen wurden. Ansonsten sind es drei statt sechs. Aber prinzipiell kann man das so stehen lassen.

Wie siehts mit sowas aus:

Code: Alles auswählen

print( "%d", (muster & WINDOWFLAG_RESIZEABLE) != 0 );
Was kommt raus, wenn man das != 0 weglässt? :-)
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Xeon
Beiträge: 41
Registriert: So Dez 17, 2017 4:10 pm

Re: Binäre Operationen

Beitrag von Xeon » Do Feb 06, 2020 3:39 pm

Du hast das f bei printf vergessen. Es kommt 4 heraus. Danke Xin, jetzt habe ich wieder was gelernt.

Ist das schon besser?

Code: Alles auswählen

#include <stdio.h>
#include <stdlib.h>

#define WINDOWFLAG_CLOSEBUTTON    0x01
#define WINDOWFLAG_BORDERLESS     0x02
#define WINDOWFLAG_RESIZEABLE     0x04
#define WINDOWFLAG_FULLSCREEN     0x08
#define WINDOWFLAG_ALWAYSONTOP    0x10
#define WINDOWFLAG_STATICPOSITION 0x20

void bitmuster_print(void)
{
    unsigned int flags;

    flags = WINDOWFLAG_STATICPOSITION | WINDOWFLAG_ALWAYSONTOP |
            WINDOWFLAG_BORDERLESS | WINDOWFLAG_CLOSEBUTTON;

    printf("%d%d%d%d%d%d", (flags & WINDOWFLAG_STATICPOSITION) ? 1 : 0,
           (flags & WINDOWFLAG_ALWAYSONTOP) ? 1 : 0, (flags & WINDOWFLAG_FULLSCREEN) ? 1 : 0,
           (flags & WINDOWFLAG_RESIZEABLE) ? 1 : 0, (flags & WINDOWFLAG_BORDERLESS) ? 1 : 0,
           (flags & WINDOWFLAG_CLOSEBUTTON) ? 1 : 0);

}

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8531
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Binäre Operationen

Beitrag von Xin » Do Feb 06, 2020 4:58 pm

Xeon hat geschrieben:
Do Feb 06, 2020 3:39 pm
Du hast das f bei printf vergessen.
In meiner eigenen Sprache heißt es nur print, wobei ich mir dort gerade versuche "puts" anzugewöhnen, welches implizit das Newline mitausgibt. :-D
Xeon hat geschrieben:
Do Feb 06, 2020 3:39 pm
Es kommt 4 heraus. Danke Xin, jetzt habe ich wieder was gelernt.
Und warum? ^^
Xeon hat geschrieben:
Do Feb 06, 2020 3:39 pm
Ist das schon besser?

Code: Alles auswählen

    printf("%d%d%d%d%d%d", (flags & WINDOWFLAG_STATICPOSITION) ? 1 : 0,
           (flags & WINDOWFLAG_ALWAYSONTOP) ? 1 : 0, (flags & WINDOWFLAG_FULLSCREEN) ? 1 : 0,
           (flags & WINDOWFLAG_RESIZEABLE) ? 1 : 0, (flags & WINDOWFLAG_BORDERLESS) ? 1 : 0,
           (flags & WINDOWFLAG_CLOSEBUTTON) ? 1 : 0);
Okay, das ist optisch jetzt nicht mehr der Burner, aber das kann man ja auch hübscher untereinander schreiben. :-)

Aber da ist wohl alles relevante drin. 8-)
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Xeon
Beiträge: 41
Registriert: So Dez 17, 2017 4:10 pm

Re: Binäre Operationen

Beitrag von Xeon » Mo Feb 10, 2020 2:38 pm

Xin hat geschrieben:Und warum? ^^

Bei "muster" sind mehrere Bits gesetzt und auch das 2. Bit. Bei "WINDOWFLAG_RESIZEABLE" ist nur das 2. Bit gesetzt. Durch das "&" werden die Bits die in "muster" und "WINDOWFLAG_RESIZEABLE" gesetzt sind auch im Ergebnis gesetzt. Das 2. Bit steht für die Zahl 4, darum kommt auch 4 heraus:

Code: Alles auswählen

printf( "%d", (muster & WINDOWFLAG_RESIZEABLE) );

Zuerst wird der Ausruck "muster & WINDOWFLAG_RESIZEABLE" berechnet, es kommt vier heraus. Würde man "!=0" einfügen wie unten, so wird geprüft ob die Bedienung true oder false ist. Ist sie false so wird 0 zurückgeliefert ist sie true wird 1 zurückgeliefert. Darum kommt 0 oder 1 heraus:

Code: Alles auswählen

printf( "%d", (muster & WINDOWFLAG_RESIZEABLE) != 0 );


Ich wusste nicht das man "!=" auch bei Funktionen setzen kann. Vorher habe dies nur z.B. in "If()" oder "while()" gekannt.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8531
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Binäre Operationen

Beitrag von Xin » Mo Feb 10, 2020 3:01 pm

Xeon hat geschrieben:
Mo Feb 10, 2020 2:38 pm
Xin hat geschrieben:Und warum? ^^
Bei "muster" sind mehrere Bits gesetzt und auch das 2. Bit. Bei "WINDOWFLAG_RESIZEABLE" ist nur das 2. Bit gesetzt. Durch das "&" werden die Bits die in "muster" und "WINDOWFLAG_RESIZEABLE" gesetzt sind auch im Ergebnis gesetzt. Das 2. Bit steht für die Zahl 4, darum kommt auch 4 heraus:
Es ist das dritte Bit. ^^
Ansonsten passt es. Das zweite Bit steht für 2, das erste für 1.
Xeon hat geschrieben:
Mo Feb 10, 2020 2:38 pm
Ich wusste nicht das man "!=" auch bei Funktionen setzen kann. Vorher habe dies nur z.B. in "If()" oder "while()" gekannt.
C und C++ sind sogesehen moderne Sprachen. != und == sind Operatoren wie + oder auch -. Das gilt auch für && oder ||. Sie sind also in jeglicher Form einer Expression verwendbar. Darum werden die Operatoren '=' und '==' auch unterschiedlich geschrieben, weil sie nunmal unterschiedliche Dinge tun.
Ältere Sprachen, wie Basic, haben Kontexte, wo zum Beispiel das =-Symbol mal als Zuweisung gilt, mal als Vergleich:

Code: Alles auswählen

a=4;
if( a=4 ) then print "a ist vier";
Du kannst also == oder && auch in Berechnungen einfügen.

Code: Alles auswählen

int a=4;
int b=7;
int c=1;

int result = (a == 4) * b + c;
Wenn a == 4 true ist, wird b mit 1 multipliziert. Wenn a != 4 ist, wird b mit 0 multipliziert.

Üblicher wäre aber eine Abfrage:

Code: Alles auswählen

int result = (a == 4) ? b + c : c;
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Xeon
Beiträge: 41
Registriert: So Dez 17, 2017 4:10 pm

Re: Binäre Operationen

Beitrag von Xeon » Mo Feb 10, 2020 3:35 pm

Ich habe bei 0 angefangen zu zählen: 0. Bit, 1. Bit, 2. Bit. Da habe ich mich wohl geirrt.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8531
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Binäre Operationen

Beitrag von Xin » Mo Feb 10, 2020 4:15 pm

Mal etwas grundsätzliche Semantik. :-)

Wenn Du etwas integer durchzählst, hat das erste Existierende die Nummer 1. Erstes Bit, zweites Bit, drittes Bit. Integer heißt zählbar. Ein Mensch ist integer, wenn man auf ihn zählen kann. Es gibt keine halben Schritte, entweder man geht einen ganzen Schritt oder man geht keinen.
Man kann Dinge zählen, also eine Menge bestimmen, oder man kann Distanzen zwischen Dingen ausdrücken. Das ist ein Unterschied. Wenn Du zählst ist ein Existierendes 1 Element. Und so zählst Du jedes Element beginnend mit 1.

Wenn Du etwas per Offset indizierst, also eine Distanz ausdrückst, dann stellt sich die Frage, wie weit ist etwas vom einer Startposition entfernt. Die Startposition ist häufig der Anfang einer Reihe existierender Objekte. Das Erste ist also der Anfang. Und das Erste ist 0 Schritte vom Anfang entfernt. Um vom ersten Haus am Platz zur Hausnummer 1 zu kommen, musst Du Dich 0 Häuser weit bewegen. Die 1 ist Zählnummer, die 0 ist die Entfernung vom ersten Haus.
Um vom ersten Byte des Arrays zum ersten Byte zu kommen, musst Du Dich 0 Byte bewegen. array ist der Zeiger auf das erste Byte. Das Offset ist 0. array[0] gibt das Byte zurück, welches 0 Byte vom ersten Byte entfernt ist. Intern wird einfach Zeiger auf erstes Element + 0 gerechnet - schon hat man den Zeiger auf das Element, was 0 Byte vom ersten Entfernt ist. Anschließend wird das Element zurückgegeben. Und das darfst Du auch so schreiben: *(array+0). Inhaltlich ist das gleichbedeutend.

Bei den Bits ist es noch ein wenig komplizierter. Da sitzt das erste Bit ganz rechts und repräsentiert die 1. Um an das erste Bit zu kommen, musst Du die 1 um 0 Bits verschieben. 1 << 0 ist also die Maske für das erste Bit. Um das zweite Bit zu maskieren musst Du die 1 um 1 Bit verschieben: 1 << 1. Das Verschieben gibt die Distanz an, wie weit verschoben wird.
In Diagrammen wird häufig von den Bits 0-7 gesprochen, aber hier handelt es sich nicht um gezählte Bits, sondern um deren Position bezogen zum ersten - also eben eine Distanz.

Gezählt wird immer von 1. Eine Strecke, um die man etwas verschiebt beginnt immer bei 0.
Es gilt also immer zwischen einer Menge (std::size_t) und einer Strecke (std::ptrdiff) zu unterscheiden. Eine Menge kann nur positiv sein, es kann keine Adresse existieren, die vor dem Speicher liegt: Man kann nicht in negativen Speicher zeigen, da existiert kein Speicher. In einer Straße kann keine negative Menge an Häusern existieren.
Eine Strecke kann jedoch positiv, wie auch negativ sein. Geht man vom 5. Haus -3 drei Häuser nach vorne, so landet man an Haus 2.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Antworten