Müssen Pointer Pointer immer auf Pointer zeigen ?
-
SeppJ schrieb:
Doch, sicher. C(99)-Standard, 6.3.2.3, 5-6. Leider weigert sich der pdf-Reader hier am Rechner mir den Text aus meiner Fassung des Dokuments auszuschneiden.
Es wird dort jedenfalls explizit Daten- zu Datenzeigerkonvertierung erlaubt, sofern das Alignment passt (ansonsten UB). Der nächste Absatz erlaubt das gleiche für Funktionszeiger.Ja sicher ist die Konvertierung erlaubt, aber da steht nichts davon, dass sie implizit durchgeführt wird. Im Gegenteil, in 6.5.4 steht "Conversions that involve pointers, other than where permitted by the constraints of 6.5.16.1, shall be specified by means of an explicit cast."
6.5.16.1 ist auch nicht sehr ergiebig, dort werden folgende impliziten Konvertierungen zugelassen:
* zwischen Zeigern auf kompatible Typen
* wenn ein void-Zeiger dabei ist
* Nullzeigerkonstanten nach Zeigertyp
* Zeiger nach _BoolKompatibilität zwischen Typen ist eine sehr eng gestrickte Äquivalenzrelation, auf keinen Fall sind alle Typen kompatibel.
-
Also ich gestern schlafen gegangen bin dachte ich wüsste wenigstens irgendwas. Ich weiß gar nichts. Möchte aber wenigstens die ultra Basics können das ich in meinem Übungen weiter komme.
1.) Das einzige was ich vielleicht verstanden habe
int i;
// Ein facher Zeiger sollte immer auf Variablen zeigen
int* p1 = &1;
// Wenn ich jetzt so blöd binund mir nen Pointer Pointer bauen will, dann muss // sollte ? ich diesen auf einen normalen Pointer zeigen lassen
int** p2 = &p1;
// Und zum letzten mal weil so schön ist. Ich baue mir einen *** und dieser muss ? auf einen ** zeigen
int***p3 = &p2Ich hoffe wenigstens das passt... wenn man das in ein Schema reinbringen.
* zeigt auf Adresse von Variablen
** zeigt auf Adresse von *
*** zeigt auf Adresse von ** uswDie kleine Zwischenfrage drängt sich auf warum man wirklich ** braucht. Sobald ich eine Variable ändern will ( keinen Pointer) schreibe ich
Typ foo* = &Zu_veränderende_Variable ... und zack kann ich sie ändern ? Warum also den Aufwand antun einen ** zu erstellen auf einen * zeigen zu lassen und über diesen dann die Variable zu ändern ? Ganz kurze Antwort für sau blöde User bitte.Und hier ein kleines Beispiel von mir:
char* p = "Hello"; char** pp = &p; *p = "Funktioniert"; //klappt pp[0] = "Funktioniert"; //klappt auch //Hier der Versuche auf einzelne Elemente des Feldes zuzugreifen. printf("%c",**p); // Fehler Erhoffte mir 'F' printf("%c",p[0][1]); // Fehler Erhoffte mir 'u'
p.s Schaue mir das Beispiel von oben noch genauer an. Aber habe wenig Hoffnung
-
p ist nur ein einfacher Zeiger.
Und du benutzt ihn bei printf wie einen Doppelzeiger.
Schreib da pp hin und es passt.Das
*p = "Funktioniert";
ist auch falschchar *p = "Funktioniert"; // ist richtig, da es die Varialendefinition ist .. *p = "Funktioniert nicht"; // ist falsch p = "Richtig" ; // ist richtig
-
** sind natürlich gerechtfertigt, da reicht ein Blick auf
int main(int argc,char**argv)
** repräsentiert hier eine String-Liste.
Das kannst du dann endlos weiterführen:
wie sieht ein Zeiger auf eine Stringliste aus? (z.B. für die Übergabe einer Stringliste an eine ändernde Funktion)char ***
Und schon hast du sogar 3 Ebenen.
-
[quote="DirkB"]
Schreib da pp hin und es passt.
/quoteDanke, hab den falschen Zeiger genommen.2 Mal nämlich. Habe mich bisschen rumgespielt mit den Pointern. Danke soweit gehts eigentlich bis auf zwei Sachen.
char* p = "Hello"; char** pp = &p; //Erste Frage printf("%c\n",**pp); //Gibt erstes Zeichen Haus. pp++; // Möchte den Pointer um eine Speicherstelle erhöhen um auf 'e' zu kommen Fehler printf("%c\n",**pp); //Hier sollte 'e' rauskommen //2 Frage printf("%c\n",**pp+1) //Erhöht den ASCII Wert um 1ns ... anstatt das er die nächste Stelle ausgeben würde :(
-
1. Pointerarithmetik ist dir bekannt?
int werte[] = {1,2,3}; printf("%d", *(werte+1));
Ergibt "2", anstatt, so wie du es vielleicht vermuten würdest, irgendwelchen Datenmüll.
2. Operatorpriorität.
-
//2 Frage
printf("%c\n",**pp+1) //Erhöht den ASCII Wert um 1ns ... anstatt das er die nächste Stelle ausgeben würde
**pp ist ja auch ein char. So wie es bei der Definition steht.
Und was erwartest du bei c+1?char c, *p, **pp; // c, *p und **pp sind jeweils char
p und *p sind Zeiger auf charNoch als Anmerkung:
Wenn du schreibst
char* p, c;
dann ist p ein Zeiger und c ein char, weil es das gleiche ist wie
char *p, c;
-
SeppJ schrieb:
1. Pointerarithmetik ist dir bekannt?
int werte[] = {1,2,3}; printf("%d", *(werte+1));
Ergibt "2", anstatt, so wie du es vielleicht vermuten würdest, irgendwelchen Datenmüll.
Ja ist mir Bekannt sonst würde ich nicht auf die Idee kommen das sowas überhaupt geht. Dein Beispiel hilft mir bei meinem Problem nicht weiter.
char* p = "Hello"; char** pp = &p; printf("%c\n",**pp); //Was muss hierher damit das unten das Zeichen e ausgeben wird ? // **(pp+1); oder *(pp+1) geht schon mal nicht :(. printf("%c\n",**pp); // hier soll e gedruckt werden
thx für 2
-
Bullz schrieb:
SeppJ schrieb:
1. Pointerarithmetik ist dir bekannt?
int werte[] = {1,2,3}; printf("%d", *(werte+1));
Ergibt "2", anstatt, so wie du es vielleicht vermuten würdest, irgendwelchen Datenmüll.
Ja ist mir Bekannt sonst würde ich nicht auf die Idee kommen das sowas überhaupt geht. Dein Beispiel hilft mir bei meinem Problem nicht weiter.
Wenn ein Zeiger auf Integer bei Erhöhung auf den nächsten Integer gesetzt wird, auf was wird dann wohl ein Zeiger auf Zeiger auf char bei Erhöhung gesetzt?
-
Wie in der Schule
Den nächsten Char was er bei mir aber nicht tut.
Ich könnte die scheiß Pointer vom 10 Stock gerade werfen.
**(pp+1); schaut doch eh recht gut aus... warum macht der Compiler nicht das was ich will ?
-
Bullz schrieb:
Den nächsten Char was er bei mir aber nicht tut.
Was daran liegt, dass diese Antwort falsch ist.
int *i; char **c; ++i; // Zeigt auf den nächsten int ++c; // Du sagst: Zeigt auf den nächsten char
Ist das nicht inkonsequent? Ich schreibe es mal anders:
typedef int my_int_type; typedef char* my_char_ptr_type; my_int_type *pointer_to_my_int_type; my_char_ptr_type *pointer_to_my_char_ptr_type; ++pointer_to_my_int_type; // Zeigt auf den nächsten my_int_type ++pointer_to_my_char_ptr_type; // Worauf zeigt dies?
**(pp+1); schaut doch eh recht gut aus... warum macht der Compiler nicht das was ich will ?
Du musst dich wieder fragen, welchen Wert du um 1 erhöhen willst.
**p
wolltest du wohl nicht um 1 erhöhen, denn das war der erste char selbst.pp
willst du wohl auch nicht um eins erhöhen, denn das ist der Zeiger, der auf den anderen Zeiger zeigt, der auf den ersten char zeigt.warum macht der Compiler nicht das was ich will ?
Der Computer macht ganz genau das, was du ihm sagst. Wenn du ihm etwas anderes sagst, als du willst, dann macht er folglich nicht das, was du willst. Die Schuld liegt aber da drin, dass du nicht richtig ausdrückst, was du möchtest.
-
Bullz schrieb:
**(pp+1); schaut doch eh recht gut aus... warum macht der Compiler nicht das was ich will ?
Weil der Compiler macht, was du ihm sagst.
Mit *(pp+1) schaltest du auf den nächsten Zeiger und greifst dann auf das Zeichen zu.
pp zeigt dann nicht mehr auf p, sondern daneben. Und da ist kein gültiger char.JEtzt fehlt noch die dritte Möglichkeit: *(*p+1)
-
vielen dank für die Mühe an euch beiden. Wäre auf das nie gekommen. Habe diese Syntax noch bei keinem Beispiel gesehen. Habe jetzt mal alles notiert und werde weitermachen. Bin wahrscheinlich zu blöd um diese einwandfrei zu verstehen
Die letzte wichtige Erkenntnis zum Schluss war noch
int** a;
**a ist vom typ int // das war mal nicht schlechtchar c = 'c' char* p1 = &c; char** p2 = &p1; **p2 = 'x'; // Das ist sinnvoll. Hoffe ich jedenfalls *p2 = 0x1234; //sinnlos da irgendwo hinzeigt ? p2 = 0x9876; //sinnlos da irgendwo hinzeigt ?
p2 -> p1 ->c
&p2 irgendwo
value p2: 0x500&p1 0x500
value 0x200&i 0x200
value charWenn ich jetzt schreibe
*p2 = 0xf00
schaut das dann nicht folgenderweise aus
&p2 irgendwo
value p2: 0x500&p1 0x500
value 0xf00&i 0x200
value intIrgendwie seh ich da keinen Sinn dahinter. Zerstöre ich mir dadurch doch nur das mein p1 nicht mehr auf &i zeigt ...
-
Im großen und ganzen richtig (Die Syntax bei "a**" ist falsch. "**a" muss das heißen).
Bullz schrieb:
Irgendwie seh ich da keinen Sinn dahinter.
Du hast korrekt erkannt, dass es selten sinnvoll ist, einem Zeiger direkt einen Zahlenwert (außer vielleicht 0) zuzuweisen.
-
ich hab schon bissi java Programmiert aber ich bin noch nie wo so lange dran gesessen wie an den Pointern...
Mit Feldern kann ich wesentlich einfacher arbeiten... sobald irgendetwas komplett neues auf mich zukommt steh ich wieder blöd da.
Würde ja auf diesen Teil gern verzichten. Komme mit der Feldnotation wesentlich besser zurecht aber dann werd ich kaum fremden Code lesen können.
int main(int argc,char* argv[]) { //.... // Leicht verständlich und funktioniert bestens switch (argv[2][0]) // Durch reines rumprobieren ohne Hirn switch (**(argv+2)) // { case '+': /... } }
Was wäre aber wenn ich auf argv[2][1] mit Pointernotation zugreifen wollen würde ?
Meine vielversprechenden weltenverbesserenden Ansatz
switch(*argv+1*(argv+2));Das beste ist er frisst es sogar. Bekomme aber Fehlermeldung:
Ungültiger Operanden für binäres * (haben int und char**)
-
*argv+1*(argv+2)); ^ Der * ist der Multiplikationsoperator. Der braucht zwei Operanden. Daher binär Die 1 ist ein int und (argv+2) ist char**
`
argv+2 ist wie argv[2] (ein char)
*(*argv+2) ist argv[2][0] (ein char. Es wird auch zweimal dereferenziert (mit zwei *))
*((*argv+2)+1) ist argv[2][1]`
-
danke... jetzt verstehe ich langsam wie das mit den Pointern geht. Ist ja wie mit Feldern nur ein wenig verkehrt gedacht ...
Trotzdem funktioniert dein Statement nicht bei mir
switch(argv[2][1]) // funktioniert switch(*((*argv+2)+1)) // dont work
-
Schäm.
Da waren die Klammern falsch
`(argv+2) ist wie argv[2] (ein char)**(argv+2) ist argv[2][0] (ein char. Es wird auch zweimal dereferenziert (mit zwei *))
((argv+2)+1) ist argv[2][1]`