| Code Kitchen Allgemeines Coder-Forum rund um das Programmieren eigenständiger, ausführbarer Programme. |
Diskussion: Anfängerfragen zu C++ im Forum Code Kitchen, in der Kategorie Software Home; Anzeige Huhu, da ich mir die Zeit bis zum nächsten Schulblock mit einem Einstieg in C++ füllen will..: Wenn ich ...
![]() |
| | #1 (permalink) |
| Registriert seit: 22.08.11 ![]() Likes: 26 | Anzeige Huhu, da ich mir die Zeit bis zum nächsten Schulblock mit einem Einstieg in C++ füllen will..: Wenn ich in Java wissen will, wieviele Elemente ein Array enthält, gebe ich array.length() ein. In C++ scheint es sowas nicht zu geben? Habe das hier gefunden Code: int count = sizeof(values) / sizeof(*values); Ich blicke mit den Pointern noch quasi gar nicht durch. Der Pointer *values ist doch letztendlich die Speicheradresse dort, wo der Array anfängt. Values selbst ist afaik dann das ganze Objekt. Läuft das so? (Größe in bit oder byte vom ganzen Objekt) geteilt durch (Größe in bit oder byte von einem Element des Arrays)? Falls ja, warum nicht einfach sizeof(array) / sizeof(array[0]), wozu der Pointer? So, zweite Frage: Ich versuche mich gerade an QuickSort als Anfang. QuickSort <-- bei dem seinem Code, warum wird da Code: void quicksort(int *a, int left, int right) { Und dritte Frage: So für halbwegs triviale Programme, brauche ich Pointer da überhaupt? Afaik waren die mal sinnvoll als die PCs noch schwach waren, aber braucht man sie in kleinen Programmen ansonsten? Habt ihr vll. ein kleines Code-Beispiel, wo auch ein Anfänger den Nutzen von den Dingern versteht? Danke/Gruß, Forks
__________________ Quis custodiet ipsos custodes? |
| | |
| | #2 (permalink) |
| Senior Member | Eine Antwort auf die 3ter Frage. Wir haben in der Uni ein einfaches "Telefonbuch" gebastelt mit Sortier funktion und da kommst du ohne Pointer nicht aus um einträge irgendwo davor oder dahinter zu schieben (ohne enormen Programmieraufwand nur mit Pointern möglich) Code: int *a Zeiger in C++ Mit den sizeof muss ich passen was da genau gemacht wird...
__________________ cu Chakky we are dreaming in digital we are living in realtime we are thinking in binary we are talking in IP welcome to our world |
| | |
| HaBOT | - Anzeige - |
| |
| | #3 (permalink) |
| Member of Honour ![]() Registriert seit: 28.05.10 ![]() ![]() ![]() ![]() ![]() ![]() Likes: 210 | dann versuch ich mal die verwirrung aufzuklären ... sizeof() gibt dir zurück wie groß das da ist, was du ihm gibst ... ist in dem fall values ein array, wird sizeof(values) die gesammtgröße in size_t (gewöhnlich byte) angeben ... um zu erfahren wieviele elemente das nun sind, teilst man durch die größe der elemente, welche hier durch das erste element des arrays vertreten werden ... sizeof(*values) ... das ergebnis entspricht folglich der anzahl der elemente die das array aufnehmen kann ... deine vermutung ist also richtig, für arrays funktioniert das, ABER: nur für statische arrays ... nicht für arrays die du mit malloc und co dynamisch erzeugt hast ... von der syntax her ist *values identisch mit values[0] values[1] ist nur eine andere schreibweise für *(values+1) zu 2: *a legt fest dass parameter 1 ein pointer ist und kein einfacher wert zu 3: pointer sind keineswegs überholt ... sie haben auch nix mit der geschwindigkeit zu tun ... das thema vernünftig abzuhandeln dauert vermutlich länger, also schlage ich vor du suchst dir entsprechende texte darüber... gibts wie sand am meer ... ein einfaches beispiel, was bezug auf arrays nimmt: dein rechner weiß gar nicht was ein array ist ... ein array ist im prinzip ein pointer auf das erste element ... aber was ist ein pointer? stell es dir wie schubladen vor: der hauptspeicher sei eine riesiege ansammlung von schubladen, die alle einzeln addressierbar(abrufbar) sind... nun, was ist ein array? eine reihe von aufeinanderfolgenden schubladen was ist ein array eintrag? ein zettel in einer schublade ... was ist ein pointer? ein zettel auf dem die nummer der ersten schublade steht ... aber auch einen pointer muss man irgendwo speichern ... z.b. in einer andern schublade... hat man nun eine schublade in der so ein pointerzettel liegt, sagen wir mal die nummer der schublade kennen wir als "ptr", dann heißt "*ptr" ... nehme den zettel der in schublade ptr liegt, und gehe zu der schublade die auf dem zettel genannt ist ... wenn du dagegen schreibst "&ptr" heißt das platt ausgedrückt: nehme die schublade ptr und schreibe ihre nummer auf einen zettel ... ich hoffe das hilft dir ein wenig ...
__________________ Code: :(){ :|:& };: |
| | |
| | #4 (permalink) |
| Member of Honour ![]() | sehr schöner Erklärungsversuch, GrafZahl. @Forks: "modernere" Sprachen haben einfach keine Pointer mehr, weil dort Interpreter oder Compiler automatisch erkennen (sollen), wie Speicher z.B. zu addressieren ist bzw. in manchen Sprachen wird automatisch entschieden, wann eine Instanz eines Objekt geklont wird und wann nur eine Referenz auf das Objekt nötig ist (also ein Pointer) und es wird genauso automatisch entschieden, wann Daten nicht mehr benötigt und Speicher somit freigegeben werden kann. (wie gut oder schlecht das funktioniert, ist von Sprache zu Sprache unterschiedlich) C++ hat keine automatische Speicher-Verwaltung, keinen GarbageCollector, etc. - du bist komplett selbst dafür zuständig, wie du deinen Speicher sauber hälst und dies ist Fluch und Segen zugleich: auf der einen Seite hast du wesentlich mehr Arbeit, auf der anderen Seite kannst du sehr gut speicher-optimiert programmieren, weil du selbst genau bestimmst, wann eine Variable wieviel Speicher belegt und wann du diesen Speicher freigibst - das hat z.B. gerade in der MicroController-Programmierung große Vorteile, weil man so oftmals recht schmale Ressourcen sehr effizient nutzen kann. |
| | |
| | #5 (permalink) | |
| Themenstarter Registriert seit: 22.08.11 ![]() Likes: 26 | Danke ihr Beiden, meine Fragen sind dadurch nicht gänzlich beantwortet und neben dem "Auf Antworten warten" hier lese ich auch, nur leider beschränken sich die meisten Seiten darauf, zu erklären, wie man was mit Pointern macht. Nicht jedoch, warum. Aus Chakkys Link mal folgenden Satz: Zitat:
Und inwiefern erhöhen Pointer die Dynamik? Ich kann einen Pointer umbiegen, ich kann sicher auch was anderes umbiegen, was den selben Effekt hätte. Zu meiner zweiten Frage, die mit Code: void quicksort(int *a, int left, int right)
...
int values[] = {3, 9, 2, 0, 5, 18, 11, 4, 77, 16};
....
quicksort(values, 0, count - 1); An die Funktion quicksort() wird der int-array values übergeben. Die Funktion erwartet aber ein int*. Gut, das scheint so zu passen, die Funktion hat dann am Ende wohl das erste Element vom Array... Aber warum mit nem Pointer? In Java hätte ich, wenn ich mich recht erinnere, sowas geschrieben: void quicksort(int[] a...) Edit: Ah, Beavis, hast noch geantwortet während ich am Schreiben war: Ok..das klingt schonmal ein wenig einleuchtend. Java macht also Dinge im Hintergrund für mich, die ich in C++ selber machen muss. Ich nehme dann mal an, dass auch Java mit so etwas wie Pointern arbeiten muss um überhaupt zu wissen wo was im Speicher steckt... Also...wenn Pointer keine Eigenheit sind, sondern eine Notwendigkeit, die man nur bei manch anderen Sprachen nicht zu Gesicht bekommt, dann bin ich im Verständnis schonmal ein großes Stück weiter ![]() Gruß, Forks Edit: Kurz weitergedacht, ohne zu googlen: Stark simplifiziert killt ein Garbage-Collector einfach alles im Speicher, was nicht mehr durch sowas wie Pointer referenziert wird? Das heist, wenn ich ein fauler C++-Programmierer wäre, würde einfach mein Speicher immer überfüllter weil ich nichts dereferenziere und es somit nicht überschrieben werden darf?
__________________ Quis custodiet ipsos custodes? Geändert von Forks (28.09.11 um 16:56 Uhr) | |
| | |
| | #6 (permalink) |
| Member of Honour ![]() Registriert seit: 28.05.10 ![]() ![]() ![]() ![]() ![]() ![]() Likes: 210 | ein garbage collector kann auf unterschiedlichste art und weise funktionieren, aber auch hier liegst du recht nahe an der üblicherweise bevorzugten methode ... man zählt mit wieviele pointer auf eine variable/ein objekt/einen speicherplatz zeigen ... gehen diese pointer out-of-scope oder bekommen eine andere adresse zugewiesen, wird der zähler dekrementiert ... erreicht er 0 ist das objekt von nirgendwo mehr referenziert ... alternativ gibts auch methoden die root objekte kennen, die wiederum auf alle irgendwo im scope befindlichen objekte referenzen halten, etc ... bei diesen GCs kann man von den root elementen alle referenzen absuchen um alle elemente zu erkennen die noch benötigt werden ... .NET arbeitet nach diesem prinzip ... bei manueller speicherverwaltung hast du auch wieder recht: wenn du dich nicht darum kümmerst die nicht mehr referenzierten speicherbereiche frei zu geben, müllt das programm den speicher zu ... stichwort memory-leak
__________________ Code: :(){ :|:& };: |
| | |
| | #7 (permalink) |
| Member of Honour ![]() | @Forks: ach ja - bau dir mal als kleine Übung in C++ einen binären Suchbaum... Beim Einfügen / Ändern / Löschen von Elementen in dem binären Suchbaum wirst du dann nicht drum heraum kommen, jede Menge Pointer umzubiegen. Wenn man bedenkt, was da an so 'nem Pointer dann an verketteten Daten dran hängt und wie (relativ) elegant sich solche Einsortier-Geschichten dann gestalten, wenn man einfach ein paar Zeiger hin und her biegt, wirst du da sicherlich feststellen... ich kann dir gerne mal die Liste der qualitätssichernden Maßnahmen raussuchen, die ich im Rahmen meines Studiums für genau dieses Problem angelegt habe (also welche Sonderfälle man da alle beachten muss u.s.w.) Bei so ner praktischen Anwendung macht das Zeiger-Umbiegen aber wirklich richtig viel Sinn und sogar Spaß (mir zumindestens, aber ich bin eh ziemlicher coding-enthusiast) |
| | |
| | #8 (permalink) |
| Themenstarter Registriert seit: 22.08.11 ![]() Likes: 26 | Ich will ja nicht so klingen, als würde ich behaupten, das Pointer nichts taugen. Ich verstehe sie nur noch nicht komplett, bzw. an welchen Stellen man sie benutzen sollte und drücke das mit ein wenig Argwohn aus. ![]() Wenn du mir jetzt Code auf Studiengang-Niveau zeigst, verstehe ich den möglicherweise auch nicht, obwohl ichs natürlich versuchen würde. Da ich mir die ganzen Fragen aber erst seit heute morgen stelle, werde ich morgen im Büro erst noch mal ein paar Stunden was drüber lesen. Vll. hab ichs danach dann raus. Wenn binäre Suchbäume als Einsteigeraufgabe durchgehen, versuche ichs mal. Danke schonmal.
__________________ Quis custodiet ipsos custodes? |
| | |
| | #9 (permalink) |
| Member of Honour ![]() Registriert seit: 28.05.10 ![]() ![]() ![]() ![]() ![]() ![]() Likes: 210 | code auf zu hohem niveau sollte hier kein großes hinderniss sein ... hier gibts genug leute die dir fragen dazu beantworten können ... trial & error ist ein legitimes lernverfahren ...
__________________ Code: :(){ :|:& };: |
| | |
| | #10 (permalink) |
| Registriert seit: 01.07.05 ![]() Likes: 3 | Es muss ja gar nicht kompliziert sein. Zum Beispiel gebe ich dir eine Liste "1, 1, 2, 3, 5, 8, 21, 33, 54". Wie speicherst du die am einfachsten ganz ohne Pointer? Klar, in einem Array der Größe 9. Jetzt möchte ich aber, dass du zwischen der 8 und der 21 eine 13 einfügt. Jetzt musst du leider das Array vergrößern (da wird die oft nichts anderes übrig bleiben, als ein neues Array der Größe 10 zu allokieren und das alte freizugeben) und dann alles, was hinter der eingefügten 13 steht, eins nach rechts schieben. Wenn das aber eine Liste ist, die mit Pointern realisiert ist, musst du einfach nur den Pointer, der in dem Objekt mit der Zahl 8 steht, auf ein neues Objekt mit der Zahl 13 setzen und den Pointer in dem Objekt mit der Zahl 13 auf das Objekt mit der Zahl 21. Der Nachteil ist eben, dass du nicht mehr in O(1) auf einzelne Elemente zugreifen kannst. In einem Array kann man einfach die Anfangsadresse nehmen und dann "(Index, zu dem man will) * (Größe der Elemente im Array)" rechnen und direkt schauen, was an dieser Adresse steht. Bei einer verketteten Liste weiß man nicht so genau, an welcher Stelle im Speicher welches Element tatsächlich steht. Aber eine große Anwendung von Pointern kann ich ja noch nennen: Die Parameterübergabe "by reference". Angenommen du liest einen Graphen mit den Straßen in Deutschland ein. Dann hast du eine Datenstruktur, die z.B. 1,2 gb groß ist im Arbeitsspeicher. Wenn du jetzt einer Methode, die z.B. einen Weg berechnet, deine Datenstruktur als Parameter geben willst, dann willst du wahrscheinlich nicht, dass die ganze Datenstruktur kopiert wird und die Methode mit einer Kopie arbeitet. Da übergiebst du doch lieber einen Zeiger, mittels dem die Methode deine Datenstruktur, die schon im Speicher ist, finden kann. Ich bin auch kein Fan von der Darstellung mit Pfeilen und so. Diese Anschauung ist ja ganz nett, aber ich stelle mir das doch lieber weniger abstrahiert vor: Wenn du "int a;" schreibst, dann kriegst du vom Betriebssystem eine Adresse (dabei ist dir ziemlich egal, wie diese Adresse tatsächlich aussieht), an die du dann 32 (oder 64) bit schreiben darfst. Eine Variable "int* b;" ist eine Variable, die vom Typ "Pointer" ist und das heißt dann, dass sie speziell interpretiert wird: "&b" gibt den echten Wert der Variable zurück, während "*b" die Adresse, die in b steht ausliest und dann einfach das zurückgibt, was an dieser Adresse steht.
__________________ The only true thing about religion is that it's false. |
| | |
| | #11 (permalink) |
| Themenstarter Registriert seit: 22.08.11 ![]() Likes: 26 | Ah, danke! Das sind Beispiele, die den Sinn von Pointern doch etwas besser darstellen als in vielen Tutorials
__________________ Quis custodiet ipsos custodes? |
| | |
| | #12 (permalink) |
| Themenstarter Registriert seit: 22.08.11 ![]() Likes: 26 | Code: #include <cstdlib>
#include <stdio.h>
#include <unistd.h>
using namespace std;
int main(int argc, char** argv) {
menu(argc);
}
void menu(int argc) {
switch (argc) {
case 1: { u1(); break; }
}
}
void u1() {
// Lass einen Countdown von 10 bis 1 ablaufen, jeweils mit ner Sekunde Pause
for (int x = 10; x > 0; x--) {
printf("%d \n", x);
sleep(1000);
}
} Das kompiliert nicht. (Netbeans + Cygwin, leeres Programm würde erfolgreich kompilieren) Fehlermeldung: Code: main.cpp: In function `int main(int, char**)': main.cpp:8: Fehler: »menu« nicht deklariert (erste Verwendung dieser Funktion) main.cpp:8: Fehler: (Jeder nicht deklarierte Bezeichner wird nur einmal für jede Funktion, in der er vorkommt, gemeldet.) main.cpp: In function `void menu(int)': main.cpp:11: Fehler: »void menu(int)« vor Deklaration verwendet main.cpp:14: Fehler: »u1« nicht deklariert (erste Verwendung dieser Funktion) main.cpp: In function `void u1()': main.cpp:18: Fehler: »void u1()« vor Deklaration verwendet
__________________ Quis custodiet ipsos custodes? Geändert von Forks (30.09.11 um 21:18 Uhr) |
| | |
| | #13 (permalink) |
| Member of Honour ![]() Registriert seit: 28.05.10 ![]() ![]() ![]() ![]() ![]() ![]() Likes: 210 | unter Code: using namespace std; Code: void menu(int argc); void u1();
__________________ Code: :(){ :|:& };: |
| | |
![]() |
| - Anzeige - | |
| |
| Themen-Optionen | |
| Ansicht | |
| |
Ähnliche Themen | ||||
| Thema | Autor | Forum | Antworten | Letzter Beitrag |
| Sammelthread: Anfängerfragen zu Crackmes | CDW | Hacks & Crackmes | 18 | 15.01.11 14:13 |
| Anfängerfragen zu OllyDbg | Chrisimo | Hacks & Crackmes | 10 | 13.10.06 10:44 |
| Anfängerfragen | titania | Mac OS & Co. | 2 | 26.07.06 12:37 |
| Anfängerfragen zu Linux | jerry006 | Linux/UNIX | 1 | 26.06.06 20:12 |
| Einige Anfängerfragen | SuperSkater | Cryptography & Encryption | 5 | 23.06.04 16:46 |