Hallo zusammen, ich habe mal eine Frage zum Thema Array und Zeiger in C. Folgendes: char *p[]={"Guten Tag"}; printf("%s",p[0]); Fragen: 1.)Wieso ist Variable p nur 4Byte gross? 2.)Spielt es keine Rolle welchen Datentyp ich nehme (char, int, float), warum nicht ? 3.) Muss ich nicht bei der Ausgabe mit *p[0] arbeiten, weil ich mir doch den Wert ansehen möchte? 4.) Wo genau wird der String "Guten Tag" abgelegt, kann ich auf die einzelnen Buchstaben zugreifen? gruß, Dirk
Ich versuch's mal: > char *p[]={"Guten Tag"}; > printf("%s",p[0]); > 1.)Wieso ist Variable p nur 4Byte gross? p[] ist ein Array aus Pointern auf char und enthält genau einen Pointer, nämlich den auf den String "Guten Tag" > 2.)Spielt es keine Rolle welchen Datentyp ich nehme (char, int, float), > warum nicht ? Pointer sind immer gleich groß und die Größe ist abhängig vom Prozessor/Betriebssystem > 3.) Muss ich nicht bei der Ausgabe mit *p[0] arbeiten, weil ich mir doch > den Wert ansehen möchte? %s erwartet einen Pointer, deshalb: nein. > 4.) Wo genau wird der String "Guten Tag" abgelegt, kann ich auf die > einzelnen Buchstaben zugreifen? p[0] enthält den Pointer, d.h. die Adresse, an der der String abgelegt ist. p[0][0] müßte dann der erste Buchstabe sein, wenn ich mich nicht irre. Eine andere Methode, auf die einzelnen chars dews Strings zuzugreifen wäre, den Ponter selbst weiterzuzählen: char a = *p[0]; char b = *(p[0]+1); oder char b = *++p[0]; usw. (alle Angaben ohne Gewähr, selbstverständlich)
p ist 4 Bytes groß, weil die Zeiger deines Compilers 32 Bit groß sind. Zeiger ist Zeiger. Ob auf char, int oder float ist unwichtig, da er ja nur eine vollständige Adresse enthalten muss. Es gibt auch einen Zeiger auf void, bei dem erst gar kein Datentyp festgelegt wurde. Ist gut zum Rechnen (Zeigerarithmetik). Der Befehl: char *p[]={"Guten Tag"}; bewirkt mehreres: 1. Reservieren eines Zeigers. Bei Dir 4 Byte lang. 2. Anlage einer Konstanten irgendwo im Speicher. Bei Dir: "Guten Tag\0" 3. Initialisieren von p mit der Adresse von "G". Wenn Du wissen willst wo im Speicher der String liegt: "p" weiß es.
Hallo und danke für Antworten, also wird irgendwo im Speicher eine Variable mit unbekannten Name angelegt, die den String "Guten Tag" aufnehmen kann und aufnimmt. Es müsste ja dann eine char -Variable bzw. Array sein, mir der grösse von 10 Bytes?
Ich vergaß: Vorsicht bei der Manipulation von p Am Anfang zeigt er ja auf 'G'. ++p oder p++ bewirkt, dass *p auf 'u' zeigt. Niemand außer "p" weis wo der Buchstabe "G" steht. Deshalb, wenn möglich, niemals p direkt manipulieren. Ab diesem Zeitpunkt (++p) bewirkt die Ausgabe mit >>printf("%s",p[0]);<< "uten Tag" Also im obigen Falle dass --p oder p-- nicht vergessen. Alternativ zwischenspeichern.
Solltest Du, warum auch immer, wissen wollen wo den Dein guter Tag rumhängt, so musst Du das selber in die Hand nehmen. Z.B. char TachChen [] = "Guten Tag"; char *p; ... p = TachChen; printf("%s",p);
Okey, werde das ganze mal in Ruhe durcharbeiten um die Logik zu verstehen. Eigentlich bin ich da nur zu gekommen, als ich die main-Funktion so programmierte, dass man beim Aufruf des Programmes, Parameter übergibt. void main(int argc, char*argv[]) Denn dort taucht diese Array-Zeiger Geschichte auf, die ich so noch nicht kannte.
amateur schrieb: > Es gibt auch einen Zeiger auf void, bei dem erst gar kein Datentyp > festgelegt wurde. Ist gut zum Rechnen (Zeigerarithmetik). Das nun gerade nicht, denn Zeigerarithmetik geht nicht mit Zeigern auf void. Ist auch logisch, denn der Compiler nutzt ja die Größe des Zieltyps als Basis, und void hat keine Größe. Dirk_30 schrieb: > also wird irgendwo im Speicher eine Variable mit unbekannten Name > angelegt, die den String "Guten Tag" aufnehmen kann und aufnimmt. Im Prinzip ja. Allerdings spricht C dann nicht von einer Variablen, sondern von einem Objekt. Variablen sind nämlich definiert als Objekte, die einen Namen haben. > Es müsste ja dann eine char -Variable bzw. Array sein, mir der grösse > von 10 Bytes? Ja, genau. Es handelt sich um ein Array aus const char der Länge 10. Den Inhalt darf man nicht verändern.
Dirk_30 schrieb: > Okey, werde das ganze mal in Ruhe durcharbeiten um die Logik zu > verstehen. Eigentlich bin ich da nur zu gekommen, als ich die > main-Funktion so programmierte, dass man beim Aufruf des Programmes, > Parameter übergibt. > > void main(int argc, char*argv[]) > > Denn dort taucht diese Array-Zeiger Geschichte auf, die ich so noch > nicht kannte. dein Beispiel erzeugt
1 | p |
2 | +------+ +---+---+---+---+---+---+---+---+---+---+ |
3 | | o----------------------->| G | u | t | e | n | | T | a | g | \0| |
4 | +------+ +---+---+---+---+---+---+---+---+---+---+ |
Sieh dir p selber an. Da geht einfach nur ein Pfeil raus der irgendwo hin führt. Warum also sollte die Größe dieser Pointervariable variieren, je nachdem wo der Pfeil hingeht. Pointer ist Pointer - Pfeil ist Pfeil. Mit double * Ptr; machst du eine Aussage darüber, was sich am >Ende< des Pfeiles befindet. Nämlich ein double. zb
1 | Ptr |
2 | +------+ +-------------+ |
3 | | o----------------------->| 3.141592654 | |
4 | +------+ +-------------+ |
Aber der Ausgangspunkt des Pfeiles, die Pointervariable, wird dadurch ja nicht größer oder kleiner. Das worauf dieser Pointer zeigt ist größer geworden. Aber um den "Pfeil" zu speichern, braucht man ja nicht mehr oder weniger Platz, als im Fall vorher. In double * Ptr; stecken 2 Informationen drinnen! a) der * sagt, dass die Variable ein Pointer ist, also die Adresse eines anderen 'Objektes', welches irgendwo im Speicher liegt, enthält b) das double trifft eine Aussage darüber, welchen Datentyp dieses 'Objekt', auf welches verwiesen wird, hat. Denn wenn man über den Pointer auf das Objekt zugreift, muss man ja wissen, was das ist - welchen Datentyp es hat. Ist das worauf der Pointer zeigt ein int, ein double, ein long? Wobei man nur durch den Pointer nicht unterscheiden kann, ob das worauf der Pointer zeigt, jetzt nur ein einzelnes derartiges Objekt ist, oder ob dort mehrere Objekte hintereinander abgelegt sind (vulgo: ob der Pointer auf ein Array zeigt). Aber im Regelfall weiß man dieses als Programmierer. dein main kriegt bei einem Aufruf des Programms aus der Command Line mit zb dem Kommando "test.exe arg1 arg2 /juhu"
1 | argv |
2 | +------+ +---+---+---+---+---+ |
3 | | o--------------------->| t | e | s | t | \0| |
4 | +------+ +---+---+---+---+---+ |
5 | | o-------------+ |
6 | +------+ | +---+---+---+---+---+ |
7 | | o--------+ +-->| a | r | g | 1 | \0| |
8 | +------+ | +---+---+---+---+---+ |
9 | | o-----+ | |
10 | +------+ | | +---+---+---+---+---+ |
11 | | NULL | | +-------------->| a | r | g | 2 | \0| |
12 | +------+ | +---+---+---+---+---+ |
13 | | |
14 | v |
15 | +---+---+---+---+---+---+ |
16 | | / | j | u | h | u | \0| |
17 | +---+---+---+---+---+---+ |
Also ein Array von Pointern, wobei jeder Pointer auf einen String zeigt. Wie genau der erste String aufgebaut ist, der den Namen des Programms enthält, ist nicht festgelegt und hängt vom Betriebssystem bzw. dessen Command Line Interpreter ab.
Danke für die vielen und ausführlichen Erklärungen, mit der Grafik ist mir jetzt klar geworden, wie sich die Zeiger verhalten. Und wieder etwas mehr C verstanden,.... Gruß, Dirk
Rolf Magnus schrieb: > Das nun gerade nicht, denn Zeigerarithmetik geht nicht mit Zeigern auf > void. Ist auch logisch, denn der Compiler nutzt ja die Größe des > Zieltyps als Basis, und void hat keine Größe. Der Vollständigkeit halber: Im gcc geht das schon, das ist aber eine gcc-spezifische Erweiterung. Der gcc nimmt dafür die Größe 1.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.