Pointer im Paramenter - Verständnisfrage
-
Hallo alle zusammen,
ich lerne gerade C mit dem Buch von K.N King. Jetzt bin ich bei den Pointern angekommen und denke, dass ich die auch einigermassen verstanden habe. Jetzt wird im Kapitel über Strings ein paar Funktionen der string.h vorstellt. z. B.
char *strcpy (char *s1, const char *s2);
Ich finde es noch etwas befremdlich, Pointer bei der Funktionsdefinition zu sehen. Ich verstehe auch nicht so richtig, wie ich hier den Rückgabewert zu deuten habe. wenn ich strcopy(str2, "abcd") aufurfe, wieso wird dort ein pointer vom Typ char zurückgegeben?
Zu den Parametern selbst . . . char *s1 -> Eigentlich soll ja ein String (also ein Char Array) übergeben werden, aber ich könnte ja auch einfach nur ein Char übergeben und kein String? D.h ich erkenne am Parameter eigentlich gar nicht, ob ich ein nur ein einzelnen Char oder auch wirklich ein Char Array (String) übergeben soll?
Ich habe gerade mal getest den string kleiner zu wählen.. komischerweise wird die Zeichenkette trotzdem darin gespeichert, auch wenn diese größer ist?
char str[1];
strcpy(str, "test");
printf("%s\n", str);Ausgabe ist bei mir trotzdem "test" ... aber das würde doch eigentlich gar nicht so sein?
Dann ist da noch der 2te. Parameter. Auch hier weiß ich wieder nicht anhand des Parameters, ob ich tatsächlich einen einzelen Char oder ein ganzes Array übergeben soll. Oder sagt man einfach, dass es ein array ist, weil der Pointer ja auf die erste "Speicherstelle" meiner Adresse zeigen würde? Und was hat es mit dem const auf sich? Gibt das einfach nur an, dass mit dem übergebenen Wert nichts passiert - er also nicht verändert wird?
Ich weiß. Viele Fragen - vielleicht ist jemand mal so nett und klärt mich auf. Ich danke euch !
Liebe Grüße
-
strcpy gibt s1 zurück
richtig bei char* kann man nicht erkennen, dass ein string übergeben werden soll, dass liegt daran, dass C keinen string Datentypen hat.
Der C compiler "nullterminiert" nur stringliterale und hat sonst keine Ahnung von Strings und C hat auch keine Laufzeitumgebung die das Stringhandling macht (im gegensatz zu sehr vielen anderen Sprachen).
Daraus folgt Stringhandling und das übergebe eines Strings wenn einer gefordert wird muss der Programmierer machen.Dein Beispiel enthält einen Fehler wie du schon erkannt hast, C macht aber keine Boundchecks so wird der Fehler nicht zur Laufzeit erkannt. Nach dieser Stelle ist das Verhalten des Programms undefiniert (das ist übrigens ein Bufferoverflow).
-
Ich danke dir, das hat mir sehr weitergeholfen !
-
strcpy gibt einen Wert zurück, damit du damit gleich weiter arbeiten kannst.
char str[5]; printf("%s\n", strcpy(str, "test"));
Strings in C sind eine Vereinbarung, wie sie zu handhaben sind. (Nullterminiert und genug Platz im Ziel)
Wenn du dich nicht daran hälst, ist das dein Problem, nicht das vom Compiler.
-
Hallo nochmal,
ok - so 100%ig klar mit dem Rückgabetyp ist mir das noch nicht. Also ihr sagt, strcpy gibt s1 bzw. "einen Wert" zurück.
Ich habe gerade mal gegoogled und folgende mögliche Implementierung gefunden:
#ifdef _NC_RESTRICT char *strcpy(char *restrict dest, const char *restrict src) #else char *strcpy(char *dest, const char* src) #endif { char *ret = dest; while (*dest++ = *src++) ; return ret; }
Irgendwie sieht das so aus, als würde der Ursprungswert von vom übergebenen String (*dest) nochmal extra gespeichert werden und dieser dann zurückgegeben werden. Mit meinem Java Verständis würde ich sagen, ich könnte sowas machen
str[] = "test123";
str2 = strcpy(str, "cop");dann müsste str den Wert "cop" beinhalten und str2 den UrsprungsWert von str2.
Ich weiß zwar das diese Zuweisung nicht funktioniert ( finde es noch etwas verwirrend wann man etwas zuweisen kann und wann nicht)., aber prinzipell ist das doch richtig gedacht das strcpy den Ursprungswert zurückgibt oder? Meine Frage: Wie kann ich denn damit weiter arbeiten? Weil eigentlich könnte das ja auch eine void funktion sein die nichts zurückgibt sondern einfach die übergebene Zeichenkette in den übergebenen String speichert.
-
am Ende von deinem Beispiel enthält str2 die Adresse von str genauer vom ersten element von str also &str[0], und nicht den Wert "cop".
Ab dieser Adresse wird es so aussehen cop\0123\0 (\0 meint hier Nullbyte)bei dem strcpy wird der Wert von dest in ret gespeicher, weil in der Schleife der Wert von dest verändert wird,
achtung bei der übergabe zerfällt das array zu einem zeiger auf das erste element des arrays
-
so hab ein kleines Programm geschrieben, da kannst du es dir angucken
#include <stdio.h> #include <string.h> int main(void) { char str[] = "test123"; char *str2 = NULL; str2 = strcpy(str, "cop"); printf("str = %p\n", str); printf("str2 = %p\n", str2); for(int i=0; i < 8; i++) { if(str[i] != '\0') putchar(str[i]); else fputs(" \\0 ", stdout); } putchar('\n'); }
-
gary1195 schrieb:
am Ende von deinem Beispiel enthält str2 die Adresse von str genauer vom ersten element von str also &str[1],
Das erste Element hat den Index 0. Immer!
Also&str[0]
Kujuk schrieb:
... finde es noch etwas verwirrend wann man etwas zuweisen kann und wann nicht ...
Variablen (dazu gehören auch Zeiger/Pointer) kannst du etwas zuweisen.
Arrays dagegen nur bei der Definition.
-
Danke euch vielmals - jetzt ists klar
!
-
DirkB schrieb:
Das erste Element hat den Index 0. Immer!
char *gegenbeispiel = str[-1]; gegenbeispiel[1] // erstes Element von str
-
nimmer schrieb:
DirkB schrieb:
Das erste Element hat den Index 0. Immer!
char *gegenbeispiel = str[-1]; gegenbeispiel[1] // erstes Element von str
Er meint wahrscheinlich auch die blanke Adresszuweisung an den Pointer. Klar, dass man durch Spielerreien etwas tricksen kann - verwirr den TE doch nicht unnötig !
-
nimmer schrieb:
DirkB schrieb:
Das erste Element hat den Index 0. Immer!
char *gegenbeispiel = str[-1]; gegenbeispiel[1] // erstes Element von str
undefiniert.
char *gegenbeispiel = str[1]; gegenbeispiel[-1] // erstes Element von str
so funktioniert es.