Hackerboard Wiki HaboBlog
Hackerboard bei Facebook Hackerboard bei Google+ Hackerboard bei Twitter

[HaBo]

 
Code Kitchen Allgemeines Coder-Forum rund um das Programmieren eigenständiger, ausführbarer Programme.

Anfängerfragen zu C++

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 ...

Like Tree4Likes

Antwort
Alt 28.09.11, 14:58   #1 (permalink)
 
Registriert seit: 22.08.11
Forks Leistung: 8086
Likes: 26
Standard Anfängerfragen zu C++

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);
(values ist ein Array) und es funktioniert wohl auch, aber warum? Was passiert da?
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) {
geschrieben, was bringt mir das *a?

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?
Forks ist offline   Mit Zitat antworten
Alt 28.09.11, 16:07   #2 (permalink)
Senior Member
 
Benutzerbild von Chakky
 
Registriert seit: 28.10.03
Chakky Leistung: 8086
Chakky eine Nachricht über ICQ schicken
Likes: 110
Standard

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
heist du Initialisierst einen Pointer mit den Datentyp Integer auch nochmal hier gut erklärt:
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
Chakky ist offline   Mit Zitat antworten
   
HaBOT
 
- Anzeige -

Werbung ist gerade online    
Alt 28.09.11, 16:12   #3 (permalink)
Member of Honour
 
Benutzerbild von GrafZahl
 
Registriert seit: 28.05.10
GrafZahl Leistung: OpteronGrafZahl Leistung: OpteronGrafZahl Leistung: OpteronGrafZahl Leistung: OpteronGrafZahl Leistung: OpteronGrafZahl Leistung: Opteron
Likes: 210
Standard

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 ...
beavisbee and xrayn like this.
__________________
Code:
:(){ :|:& };:
Veritas Aequitas
GrafZahl ist offline   Mit Zitat antworten
Alt 28.09.11, 16:33   #4 (permalink)
Member of Honour
 
Benutzerbild von beavisbee
 
Registriert seit: 22.02.07
beavisbee Leistung: Pentium IIIbeavisbee Leistung: Pentium IIIbeavisbee Leistung: Pentium IIIbeavisbee Leistung: Pentium III
beavisbee eine Nachricht über ICQ schicken
Likes: 77
Standard

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.
beavisbee ist offline   Mit Zitat antworten
Alt 28.09.11, 16:52   #5 (permalink)
Themenstarter
 
Registriert seit: 22.08.11
Forks Leistung: 8086
Likes: 26
Standard

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:
...Sie sprechen Sie normalerweise über den Variablennamen an, so wie Sie das Auto auch über das Kennzeichen erreichen können. Sie können aber auch eine Zeigervariable definieren, die einer Magnetkarte entspricht. Wenn Sie der Zeigervariablen die Adresse einer Variablen zuweisen, können Sie über die Zeigervariablen auf diese Variable zugreifen.
Ich habe also zwei Möglichkeiten, Pointer und den Namen der Variable. Warum Pointer?

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);
Ich verstehe, dass da ein Pointer auf ne Int erzeugt wird. Ich weis aber immernoch nicht, wozu ^^. Also..vll. liegt das echt an meiner Java-Erfahrung, dass sich mir das nicht erschließt.

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)
Forks ist offline   Mit Zitat antworten
Alt 28.09.11, 17:47   #6 (permalink)
Member of Honour
 
Benutzerbild von GrafZahl
 
Registriert seit: 28.05.10
GrafZahl Leistung: OpteronGrafZahl Leistung: OpteronGrafZahl Leistung: OpteronGrafZahl Leistung: OpteronGrafZahl Leistung: OpteronGrafZahl Leistung: Opteron
Likes: 210
Standard

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:
:(){ :|:& };:
Veritas Aequitas
GrafZahl ist offline   Mit Zitat antworten
Alt 28.09.11, 19:39   #7 (permalink)
Member of Honour
 
Benutzerbild von beavisbee
 
Registriert seit: 22.02.07
beavisbee Leistung: Pentium IIIbeavisbee Leistung: Pentium IIIbeavisbee Leistung: Pentium IIIbeavisbee Leistung: Pentium III
beavisbee eine Nachricht über ICQ schicken
Likes: 77
Standard

@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)
beavisbee ist offline   Mit Zitat antworten
Alt 28.09.11, 19:53   #8 (permalink)
Themenstarter
 
Registriert seit: 22.08.11
Forks Leistung: 8086
Likes: 26
Standard

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?
Forks ist offline   Mit Zitat antworten
Alt 28.09.11, 20:51   #9 (permalink)
Member of Honour
 
Benutzerbild von GrafZahl
 
Registriert seit: 28.05.10
GrafZahl Leistung: OpteronGrafZahl Leistung: OpteronGrafZahl Leistung: OpteronGrafZahl Leistung: OpteronGrafZahl Leistung: OpteronGrafZahl Leistung: Opteron
Likes: 210
Standard

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:
:(){ :|:& };:
Veritas Aequitas
GrafZahl ist offline   Mit Zitat antworten
Alt 28.09.11, 22:24   #10 (permalink)
 
Benutzerbild von Chris_XY
 
Registriert seit: 01.07.05
Chris_XY Leistung: Z3
Likes: 3
Standard

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.
beavisbee likes this.
__________________
The only true thing about religion is
that it's false.
Chris_XY ist offline   Mit Zitat antworten
Alt 28.09.11, 22:51   #11 (permalink)
Themenstarter
 
Registriert seit: 22.08.11
Forks Leistung: 8086
Likes: 26
Standard

Ah, danke! Das sind Beispiele, die den Sinn von Pointern doch etwas besser darstellen als in vielen Tutorials
__________________
Quis custodiet ipsos custodes?
Forks ist offline   Mit Zitat antworten
Alt 30.09.11, 21:16   #12 (permalink)
Themenstarter
 
Registriert seit: 22.08.11
Forks Leistung: 8086
Likes: 26
Standard

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);
    }
}
(switch, weil das später ein Kommandozeilenparameter-"Menü" werden soll für 17 verschiedene Funktionen/Aufgaben)...

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
Was soll ich da noch deklarieren?
__________________
Quis custodiet ipsos custodes?

Geändert von Forks (30.09.11 um 21:18 Uhr)
Forks ist offline   Mit Zitat antworten
Alt 30.09.11, 22:18   #13 (permalink)
Member of Honour
 
Benutzerbild von GrafZahl
 
Registriert seit: 28.05.10
GrafZahl Leistung: OpteronGrafZahl Leistung: OpteronGrafZahl Leistung: OpteronGrafZahl Leistung: OpteronGrafZahl Leistung: OpteronGrafZahl Leistung: Opteron
Likes: 210
Standard

unter

Code:
using namespace std;
füge mal bitte diese zeilen ein:
Code:
void menu(int argc);
void u1();
hintergrund: du solltest funktionen deklarieren bevor du sie verwendest, oder deffinierst.
__________________
Code:
:(){ :|:& };:
Veritas Aequitas
GrafZahl ist offline   Mit Zitat antworten
Alt 30.09.11, 22:24   #14 (permalink)
Themenstarter
 
Registriert seit: 22.08.11
Forks Leistung: 8086
Likes: 26
Standard

Ist das wieder sowas, was Java von alleine macht und C++ nicht? Oder ist nur mein Compiler zu pingelig eingestellt?
__________________
Quis custodiet ipsos custodes?
Forks ist offline   Mit Zitat antworten
Alt 30.09.11, 23:15   #15 (permalink)
Member of Honour
 
Benutzerbild von GrafZahl
 
Registriert seit: 28.05.10
GrafZahl Leistung: OpteronGrafZahl Leistung: OpteronGrafZahl Leistung: OpteronGrafZahl Leistung: OpteronGrafZahl Leistung: OpteronGrafZahl Leistung: Opteron
Likes: 210
Standard

letzteres ... aber pingelig ist genau die einstellung auf der man lernen sollte ...
__________________
Code:
:(){ :|:& };:
Veritas Aequitas
GrafZahl ist offline   Mit Zitat antworten
Antwort
   
- Anzeige -

Werbung ist gerade online    

[HaBo] » Software Home » Code Kitchen » Anfängerfragen zu C++
Themen-Optionen
Ansicht

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks sind aus
Pingbacks sind aus
Refbacks sind aus


Ä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


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61