Zenerid hat geschrieben:Hmm .. dann habe ich das ja komplett verwechselt. Wenn ich also einen Pointer habe, dann ist ptr die SPeicheradresse und *ptr der Wert von dem Pointer
ptr ist die Bezeichnung für eine Speicherstelle, wo der Inhalt von ptr liegt. ptr ist ein (char *), also ein Pointer.
Bei int i; gibt es eine Speicherstelle irgendwo im Speicher, die Du im Programm 'i' nennst. Wenn Du 'i' schreibst, wird der Inhalt der Speicherstelle benutzt.
Wenn Du ptr eingibst wird der Inhalt der Speicherstelle verwandt, die Du eben mit "ptr" bezeichnest. Statt eines integers, hast Du in der Speicherstelle die Adresse einer anderen Speicherstelle stehen. Damit zeigt "ptr" auf eine andere Adresse.
*ptr geht nun hin und nimmt den Inhalt der Speicherstelle, die Du "ptr" nennst, worin sich eben die Adresse einer anderen Speicherstelle befindet. Diese andere Speicherstelle wird nun mit '*' dereferenziert. Statt also die andere Speicherstelle anzugucken, guckst Du nun auf die Daten, die an der anderen Speicherstelle liegen, was bei einem (char const *) eben als ein (char const) interpretiert wird.
Zenerid hat geschrieben:, also dass was dann dementsprechend ebend an der Speicheradresse liegt, aber ebend nur das erste Zeichen aber man kann mit ++ dann auch wie in einem Array zeichenweise weitergehen, richtig?

ptr++ nimmt die Daten aus der Speicherstelle, die Du ptr nennst, was eine Adresse auf eine andere Speicherstelle ist, und erhöht dieses Datum um 1. Die erhöhte Adresse der anderen Speicherstelle wird dann in ptr, also an der Speicherstelle, die Du "ptr" nennst, wieder gespeichert.
Genau wie bei i++.
Zenerid hat geschrieben:Könnte ich denn aber auch nicht, wenn es sich um einen char * handelt mit
den ganzen Pointer oder was an der Speicheradresse liegt als String ausgeben oder würde das so nicht gehen?
Es gibt keine halben Pointer. Ein Pointer ist eine Zahl - eben die Nummer der Speicherstelle. Du kannst die Nummer mit %p ausgeben oder mit %s behauptest Du, dass da, wohin ptr zeigt, ein String wäre, den man ausgeben kann.
Zenerid hat geschrieben:Das mit dem ausgeben der Speicheradresse bzw. dem Pointer ist ja auch interessant aber könnte man das nicht einfach nur mit
machen oder muss man das unbedingt casten? Das ist doch ein cast?
%p ist eine Formatierungsvorschrift. Da kommt eine Zahl und die soll so ausgegeben werden, dass es wie eine Adresse aussieht. Bei %s läuft ein ganz anderes Programm ab - da wird an die Adresse geguckt und Buchstabe für Buchstabe ausgegeben, bis ein Nullbyte ankommt. Das ist kein Cast.
Das Casting, was ich mit (void*) eingefügt habe, dient dazu, den Compiler zu beruhigen, der bei %p bei mir die Warnung gibt, dass er ein (void *) wünscht. C++ castet nicht mehr automatisch nach (void*). Um die Warnung zu unterdrücken, bestätige ich mit dem Cast nach (void *), dass ich weiß, was ich da tue.
Zenerid hat geschrieben:Hehe, ja das stimmt schon. Habe ich das denn dann auch richtig verstanden, das man mit
und
auf dasselbe prüft
Die beiden Zeilen sind semantisch identisch, aber
Zenerid hat geschrieben:, also ob da NULL steht als auch ob da ein \0 steht? \0 steht doch eigentlich für das Ende eines Strings oder nicht und ist somt auch nicht dasselbe wie NULL oder liege ich da jetzt komplett falsch und beides ist identisch?
Es wird nur geprüft, ob das erste(!) Zeichen des Strings, also das auf das Buffer zeigt ein Nullbyte ist.
Falls buffer NULL ist, also ein Nullpointer, fliegt Dir das um die Ohren. Für beides wäre die Abfrage:
Zenerid hat geschrieben:Ah gut, dann hatte ich das mit dem char * ja doch schon richtig verstanden. Wenn man dann auch noch etwas bei dieser Speicheradresse speichern will, dann müsste man ja erst welchen freigeben, mit malloc oder calloc z.B. ?
Schwierige Wortwahl. Du musst beschreibbaren Speicher haben und ein String im Quelltext, wie "Hallo Welt", ist nicht beschreibbar. Du kannst Dir entweder Speicher in einem Array geben lassen:
oder Du kannst Speicher allozieren, auf den Du dann selbstverständlich auch schreiben darfst, diesen musst Du danach aber an das System zurückgeben, also aus Deiner Besetzung entlassen, umgangssprachlich: Den Speicher wieder freigeben. Das wäre dann mit malloc/calloc und free.
Zenerid hat geschrieben:Ein char Array oder generell ein Array reserviert ja selbständig den benötiigten Speicher aber was ich ja dann nicht ganz verstehe, ist wann man was verwendet. Warum wird dann bspw. für einen Buffer, wo man etwas aus einer Datei einliest oft ein char * verwendet und kein Array?
Nochmal: Ein char * zeigt wie ein char [] auf das erste Element des Arrays. Wie lang das Array ist, ist dabei eine andere Frage. Ein char single; und ein char array[1]; sind vom Prinzip das gleiche. Nur, dass Du beim array den Zeiger auf das erste Element hast, beim zweiten hast Du das char direkt. Ein Zeiger kann nun auf ein Element zeigen, zum Beispiel durch char * ptr = &single; oder durch char * ptr = array;
Greifst Du nun auf *ptr zu, wird entsprechend das char gelesen oder geändert, dessen Speicheradresse in ptr steht.
Wann nimmst Du was? Wenn Du weißt, wieviel Speicher Du brauchst und dass Du auch derjenige bist, der den Speicher wieder frei gibt, dann kannst Du ein Array verwenden: Weil der Speicher in deiner Funktion liegt. Du kannst Funktionen rufen und diesen Funktionen mit Hilfe eines Zeigers sagen, wo sie den Speicher finden. printf( "%s\n", array ) zum Beispiel.
Aber Du kannst das Array nicht an die Funktion geben, die Dich gerufen hat.
Wenn Du also nicht weißt, dass Du selbst (also die Funktion, die den Speicher gerade braucht) derjenige sein wird, der den Speicher wieder freigibt, dann musst Du alloc und free nehmen. Der Speicher liegt dann irgendwo im Computer und ist nicht von der Funktion abhängig.
Speicher anfordern kostet Zeit - wenn man drauf verzichten kann, nimmt man lieber ein Array. Wenn man Speicher anfordern muss, muss man eben Speicher anfordern.
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.