Hi, ich habe mir ein C++ Tutorial geholt und nach anfänglichen "Schwierigkeiten" hats endlich gefunkt!(oder besser gesagt ich habe angefangen, weil ich ein paar Sachen nicht verstanden habe)
Bis zu diesen 2 Punkten lief auch alles gut, bis ich zum Punkt |&! Operator etc. kam.
Ich habe es übersprungen, da ich es irgendwie Sinnlos fand, aber jetzt kommt das schlechte Gewissen, also:
1.Braucht man diese Operatoren(lustiges Wort) wirklich, wenn ja wofür?
2.Außerdem wüsste ich nochwie genau Addressen funktionieren, erklärt mir also bitte das hier(ist kopiert):
Kapitel 8
Nun geht es etwas weiter bei den Variablen. Wir lernen andere Arten von Variablen kennen - nämlich Zeiger und Referenzen. Die sind uns dann bei Funktionen ganz nützlich, denn damit können wir Speicher direkt manipulieren. Vielleicht wird es dir nicht auf Anhieb klar, warum Zeiger an einer bestimmten Stelle verwendet werden. Das wirst du aber noch mitkriegen auf deiner Programmierer-Karriere.
Zeiger
Kurze Wiederholung aus Kapitel 2:
Speicher
Speicher gibt es in absolut jedem Computer. Er dient natürlich dazu, sich Daten/Informationen zu merken. Variablen (und ein Teil von Konstanten) stellen solche Daten/Informationen dar. Dazu legt der Computer an einem bestimmten Ort - der Adresse - diese Informationen ab. Ein Programm mit Variablen muss sich zwangsläufig darum kümmern, dass das System bzw. das Betriebssystem ihm den erforderlichen Speicher zur Verfügung stellt.
Ein Computer kann immer nur so viel Speicher adressieren - d.h. ansprechen - wie er konzipiert ist. Ein 16-Bit System/Betriebssystem kann nur 65536 Byte adressieren - gerade mal ~65 KByte. Mit 32 Bit-Systemen ist schon einiges mehr möglich, denn ein solcher Computer kann bis 4294967296 Byte ansprechen - das entspricht 4 Gigabyte Speicher. Oft sind Mainboards aber auf 2 oder 3 Gigabyte begrenzt wegen fehlender RAM-Slots. Kommende bzw. derzeitige 64-Bit-Monsterrechner könnten theoretisch bis 264 Byte, also 18446744073709551616 Byte oder 16 Terabyte ansprechen!!!
Die Adresse kann so angegeben werden (auf ein 32 Bit-System bezogen): An Speicherstelle 01010101 10101010 00110011 01101100 ist der Wert 01101011 gespeichert. Das ist ein bischen umständlich und deswegen nimmt man einfach andere Zahlensysteme. Für Adressen hat sich das Hexadezimalsystem etabliert und für die Werte nimmt man das Dezimalsystem. In diesem Beispiel würde an der Adresse 55 AA 33 6C der Wert 107 stehen.
Normale Variablen dienen dem Hauptzweck, Werte zu speichern. Mit Zeigern ist das etwas anders: Zeiger beinhalten Adressen aus dem Speicher eines Computers. Die Größe in Byte einer Variable hängt immer davon ab, welchen Datentyp du einsetzt, während Zeiger immer so groß sind, wie das System unterstützt.
Ich habe zwar binär System verstanden, aber ich weiß nicht GENAU wie die anderen funktionieren (ich gestehe, das binär System hat mir mein kleiner Bruder erklärt)
Danke im Vorraus!
Ich weiß jetzt nicht genau was du mit "|&! Operator" meinst, aber ich kann dir den Gebrauch dieser Symbölchen erklären:
| ist ein bitweises logisches OR, verknüpft also zwei Variablen miteinander und setzt die Bit, welche bei mindestens einer der Variablen gesetzt sind.
Beispiel:
10000100 | 00000101 würde ergeben: 10000101
& ist ein bitweises AND, das gleiche wie oben, nur diesmal müssen beide Variablen die Bit gesetzt haben, damit das Resultat dieses Bit auch gesetzt hat:
10000100 & 00000101 würde ergeben: 00000100
(& hat noch andere Bedeutungen, mehr dazu weiter unten bei den Zeigern)
! ist der NOT-Operator. Wenn du also folgendes verwendest: variable != 0
dann wird geprüft, ob die Variable NICHT 0 ist.
Und ja, diese Operatoren könne unter Umständen sehr nützlich sein für dein Programm. Man sollte schon wissen was sie machen und wie man sie anzuwenden hat.
Zu den Zeigern:
Stell dir vor, du hast eine Variable "zahl" vom Typ int. Du weist nun der Variable den Wert 9 zu.
int zahl = 9;
Jetzt willst du, aus welchen Gründen auch immer, wissen, wo diese Variable im Speicher steht. Also brauchst du einen Zeiger der auf die Variable zeigt, genauer, auf die Stelle im Speicher.
Pointer werden bei der Erstellung (Definition oder Deklaration) mit * gekennzeichnet:
int* pointer;
(gern auch int *pointer geschrieben)
Hier zu beachten ist, dass du den Pointer vom gleichen Typ wie die Variable wählst. Also int* und nicht char* oder sowas.
Hier wird noch kein Speicherbereich zugewiesen, das soll sich jetzt ändern:
pointer = &zahl;
Hier dient der &-Operator dazu, die Speicherstelle der Variablen zu ermitteln. Eine Variable mit vorangestelltem &-Operator gibt also nicht den Wert der Variablen sondern die Speicherstelle der Variablen zurück.
Jetzt zeigt der Zeiger "Pointer" auf die Speicherstelle der Variablen Zahl.
Diesen Inhalt der Variable kann man jetzt auch über die Speicherstelle ändern. Man muss also nicht die genaue Variable kennen sondern es reicht die Speicherstelle (und der Typ aus):
*pointer = 4;
Mit dem *-Operator wird hier bei Pointern kenntlich gemacht, dass man nicht den pointer selbst ändern will sondern den Inhalt des Pointers, der Wert der also im Speicher steht.
Die Variable "zahl" hat von nun an den Wert 4, obwohl wir sie garnicht verändert haben. Wir haben direkt den Speicher verändert, was unter Umständen sehr hilfreich ist.
Achtung: Würde man nur pointer = 4 schreiben, würde der Pointer auf den Speicher bei Stelle 4 zeigen und höchstwahrscheinlich bei weiteren Operationen einen Speicherfehler verursachen. Vorsicht ist also geboten! Soll der Inhalt geändert werden, muss der *-Operator verwendet werden. Mit Pointern kann man sich leicht Speicherfehler bauen, wenn man sie falsch anwendet. Richtig angewendet sind sie aber eine sehr mächtige Sache um komplexe Programme erst zu ermöglichen. Du solltest dich also durchaus damit vertraut machen. (Such mal bei google nach Pointer-Tutorials bzw. Zeiger-Tutorials für C++ )
So, das wären jetzt so die absoluten Grundlagen für Pointer, ich hoffe du kannst damit was anfangen. Ansonsten such dir im Web noch andere Tutorials mit denen du vielleicht besser zurecht kommst.
Noch eine kleine Anmerkung zum NOT-Operator ...
Ynnus hat ja schon erwähnt, was bei einer OR- und einer AND-Operation passiert. Bei einer NOT-Operation werden die Bits einfach nur umgekehrt. Für eine NOT-Operation ist nur ein Operand nötig und nicht zwei. Exempli gratia:
! 10000100 = 01111011
Übrigens kann man das auch sehr schön mit dem Windows-Taschenrechner nachvollziehen (Start->Programme->Zubehör->Rechner). Du musst ihn nur unter "Ansicht" auf "Wissenschaftlich" stellen, und schon kannst du Zahlen in binärer Form eingeben ("bin" aktivieren) und logische Operationen durchführen (And, Or, Xor und Not).
Danke, das mit den | oder ! nichts Operatoren habe ich schon gewusst, nur ich weiß einfach nicht wofür die gut sein sollten (deshalb kann ich sie nicht auswendig). Die Zeiger an sich (nicht der Speicher, der wurde schon vorher erklärt) werden gerade in meinem TUT erklärt, wenn auch etwas schwerer zu verstehen.
Wenn du abfragen möchtest, ob z.B. eine Variable nicht leer ist und du sie somit verwerten kannst, da du sonst möglicher Weise eine Fehlermeldung bekommen würdest, kannst du mit einem NOT dies eben prüfen.
Wenn du dir z.B. überlegst, du hättest ein Eingabeformular gemacht (jetzt nur rein theoretisch). Der Nutzer soll dort einige Daten schreiben und dann einen "Senden"-Button drücken. Zur Sicherheit lässt du dann z.B. abfragen, ob er wirklich einen Namen, seine E-Mail-Adresse oder weiß der Kuckuck was angegeben hat.
Hoffe ich als Nicht-C++-Pr0gg3r konnte es richtig erklären.
Nach der theoretischen Erklärung der Bit-Operatoren mal ein etwas praktischer Einschub.
Wie gesagt verbinden sie bitweise zwei Variablen miteinander. Ein boolscher Ausdruck, der in einem If abgefragt wird, ist im Grunde genau ein Bit. Entweder ergibt er TRUE (1) oder False (0). Mithilfe der boolschen Operatoren OR (|), AND (&) und NOT (!), kann man jetzt zwei oderer mehrer dieser Ausdrücke verbinden und erhält als Ergebnis wieder einen einfachen boolschen Ausdruck.
Beispiel:
Wir haben uns ein zusätzliches if gespart und damit insgesamt zwei Zeilen. Auf diesselbe Art kann man das OR (|) benutzen, dann ergibt der Gesamtausdruck TRUE, sobald eines der beiden mit OR verknüpften Glieder TRUE ergibt.
NOT läßt sich wie gesagt auf einen Ausdruck anwenden und ergibt TRUE, wenn der Ausdruck selber FALSE ergibt.
Diese drei Operatoren lassen sich natürlich auch beliebig, mithilfe von Klammern, kombinieren.
Allgemein lässt sich mit diesen Operatoren sehr oft Schreibarbeit einsparen, insbesondere bei Abfragen mehrer zusammenhängender Ausdrücke, die man dann alle in ein if reinpacken kann.
Neben der Anwendung in ifs, lassen diese Ausdrücke sich natürlich auch benutzen um direkt bitweise mit Werten zu arbeiten, das kommt in der Regel aber seltener vor. Sehr verbreitet ist dabei aber die Methode mithilfe des OR, bitweise Flags von irgendwelchen Libarys zu verknüpfen.
Wenn FLAG1 jetzt die Zahl 01 ist und FLAG2 die Zahl 10, wird der Funktion die OR-Verknüpfung beider Zahlen übergeben, in diesem Fall 11. Mithilfe von AND und NOT, kann die Funktion dann überprüfen ob ein bestimmtes Bit, und damit ein bestimmtes Flag, gesetzt ist und entsprechend reagieren.
Dadurch kann man einer Funktion eine Vielzahl von An- und Ausschaltbaren Optionen beibringen, ohne den Funktionsaufruf durch unzählige weitere Argumente zu überladen, weil die Flags zusammen nur als 1 Wert übergeben werden.
Geht eigentlich beides. Aber die äußeren Klammern müssen sein.
Bei ((x == 5) & (y == 3)) müssen die beiden inneren Klammern 1 sein, damit die gesammte Bedingung 1 ist, genauso wie bei ((x == 5) && (y == 3)). Das gleiche gilt auch für | bzw. ||. Den XOR-Operator (^) gibt es aber wohl nur in binärer Form.
freundliche Grüße, Rolus
Korrigiert mich, falls ich Mist laber, aber liegt der Unterschied zwischen & und && in dem Fall nicht in der Priorität mit der sie behandelt werden, was ein (x == 5 && y == 3) ohne Klammern statt ((x == 5) & (y == 3)) erlaubt?
Oder mit anderen Worten: & wird vor == und != verarbeitet, && danach.
Soweit ich mich entsinne bedeutet & und && sowie | und || dasselbe.
Der Unterschied liegt zum einen in der Priorität, was aber unwichtig ist, wenn man alles klammert, und zum anderen in der Tatsache ob der gesamte Ausdruck bearbeitet wird oder nicht.
Der Compiler überprüft, AFAIR von rechts nach links. Wenn in einer ODER-Verknüpfung der rechte Teil bereits 1 ergibt, überprüft er bei einem der beiden OR-Operatoren den linken Teil überhaupt nicht mehr, weil dessen Wert keine Rolle mehr spielt.
Bei der UND-Verknüpfung ebenso, falls der rechte Teil bereits 0 ergibt. Das kann wichtig sein, wenn ein Ausdruck einen Zugriffsfehler oder so hervorruft, sollte der andere Ausdruck 1 bzw. 0 sein.
Welcher der beiden Operatoren diese verkürzte Bearbeitung hat, weiß ich allerdings nicht mehr.
PS: Ob man das gesamte IF noch klammern muss oder nicht, spielt glaub ich hier erstmal keine Rolle, es ging nur um den eigentlichen Anwendungszweck der Operatoren. Ansonsten, verzeiht, in letzter Zeit wenig mit C gearbeitet.