Forum: Compiler & IDEs Verständnis problem bei Pointer auf ein Pointer


von Johannes H. (Gast)


Lesenswert?

Hallo liebe Forenbesucher,

wie im Betreff schon erwähnt habe ich da ein kleines Verständnis problem 
was POinter auf Pointer betrifft. Ich erkläre es mit einem Beispiel.

1
void test (int * abc){
2
3
   *abc+ = 1;
4
   return 0;
5
}
6
7
8
int main(){
9
10
   int a = 0;
11
   int * ptest = NULL;
12
   ptest =  &a;
13
14
   test(&ptest)  //Da ist mein Verständnisproblem
15
}

Das Beispiel ist ziemlich vereinfacht nur ich verstehe jetzt nicht wie 
ich ein POinter einem Argumentweiter gebe, welcher wiederrum ein POinter 
ist.

Gehört bei der übergabe das kaufmänische UND & dazu oder nicht, weil 
wenn ich es so übergebe bekomme ich die WArrnnung: expected 'int *' but 
argument is of type 'int **'.

Ich hoffe ihr könnt mir da weiterhelfen.

Lg Johannes

von Narf (Gast)


Lesenswert?

Zunächst einmal ist ptest vom Typ int*. Verwendet man ein & als 
Operator, liefert dieses die Speicheradresse zurück, an dem die Variable 
die gespeichert wird (bei int ist der Typ für diese Speicheradresse 
int*). Beispiel:
a ist vom Typ int. &a liefert einen Pointer auf int also int* (dieser 
Typ speichert die Adresse, an dem ein int steht).
Das ganze musst du jetzt nur logisch fortführen: ptest ist vom Typ int*. 
D.h. &ptest liefert einen Pointer auf int* als int** (dieser Typ 
speichert die Adresse an dem ein Pointer steht, welcher die Adresse 
eines int speichert).

Für dein Beispiel bedeutet dass:
1
void test (int** abc){
2
3
   **abc+ = 1; //zweimal dereferenzieren, weil du a verändern willst, nicht den Pointer inkrementieren
4
   return 0;
5
}
6
7
8
int main(){
9
10
   int a = 0;
11
   int * ptest = NULL;
12
   ptest =  &a;
13
14
   test(&ptest)  //Da ist mein Verständnisproblem
15
}

von Johannes H. (Gast)


Lesenswert?

Passt vielen dank so habe ich es mir eh auch gedacht aber was passiert 
jetzt, wenn ich in der test - Funktion z.B eine String funktion von 
string.h aufrufe, die als parameter ebenso einen Pointer erwartet:

1
void test (char * x){
2
3
      strcpy (?x?, "defg");  //WAs gehört da jetzt her
4
}
5
6
7
int main(){
8
9
   char buf [] = "abcd"
10
11
   test(buf);
12
}
13
[c]
14
15
16
Ich weiß jetzt nicht was ich da in den Fragezeichen setzen soll, weil wenn ich das so ausführe bekomme ich genau dieselbe Warnug nur diesmal mit char expected 'char *' but argument is of type 'char **'. 
17
18
Das Problem ist ja, dass strcpy als Prototyp so definier ist:
19
20
[c] char *strcpy(char *dest, const char *src)
.

Würde mir es gehen wenn es so definiert wäre:
1
char *strcpy(char *dest, const char **src)

und die  Übergabe an die Funktion müsste ich wahrscheinlich so machen
1
strcpy (&x, "defg");
 oder?

Da das nicht möglich ist, hoffe ich dass ihr mir da vielleicht 
weiterhelfen könnt, wie ich das lösen könnte oder ist das nicht lösbar?

Lg

von Carl D. (jcw2)


Lesenswert?

Johannes H. schrieb:
> Passt vielen dank so habe ich es mir eh auch gedacht

Schau dir die erste Antwort besser noch mal an, denn

> aber was passiert jetzt, wenn ich in der test - Funktion z.B eine
> String funktion von string.h aufrufe, die als parameter ebenso
> einen Pointer erwartet:
>
>
>
1
> void test (char * x){
2
> 
3
>       strcpy (?x?, "defg");  //WAs gehört da jetzt her
4
> }
5
> 
6
> 
7
> int main(){
8
> 
9
>    char buf [] = "abcd"
10
> 
11
>    test(buf);
12
> }
13
> [c]
14
> 
15
.
16
> Ich weiß jetzt nicht was ich da in den Fragezeichen setzen soll, weil 
17
> wenn ich das so ausführe bekomme ich genau dieselbe Warnug nur diesmal 
18
> mit char expected 'char *' but argument is of type 'char **'.
19
> 
20
> Das Problem ist ja, dass strcpy als Prototyp so definier ist:
21
> 
22
> [c] char *strcpy(char *dest, const char *src)
.
>
> Würde mir es gehen wenn es so definiert wäre:
>
>
1
char *strcpy(char *dest, const char **src)
>
> und die  Übergabe an die Funktion müsste ich wahrscheinlich so machen
>
1
strcpy (&x, "defg");
 oder?


es sieht nicht so aus, als ob das schon sitzt. Zumindest der Transfer zu 
Strings, die durch einen Zeiger auf ihr erstes Zeichen repräsentiert 
werden (sowie ein '\0'-Zeichen am Ende, was bei String-Literalen 
implizit immer dabei ist)

von Sebastian V. (sebi_s)


Lesenswert?

In deinen Beispielen ist es überhaupt gar nicht nötig Pointer auf 
Pointer zu nutzen. Das macht man nur wenn die Funktion den Wert des 
Pointers verändern soll (also wohin er zeigt) oder man Arrays von 
Pointern hat. Die Daten wohin der Pointer zeigt lassen sich auch so 
verändern. Bezogen auf dein String Beispiel würde man den Code so 
schreiben:
1
void test (char * x){
2
      strcpy (x, "defg");
3
}
4
5
int main(){
6
   char buf [] = "abcd"
7
   test(buf);
8
}

: Bearbeitet durch User
von Peter D. (peda)


Lesenswert?

Sebastian V. schrieb:
> In deinen Beispielen ist es überhaupt gar nicht nötig Pointer auf
> Pointer zu nutzen.

Stimmt, um den Inhalt der Variable zu ändern, reicht ein einfacher 
Pointer.
Auch wenn man den Pointer selber ändert, ist das oftmals nicht nötig. 
Man gibt einfach den neuen Pointer zurück, wie es z.B. in der <string.h> 
sehr gerne gemacht wird.

von Mampf unterwegs (Gast)


Lesenswert?

Mit pointerpointern hat man in der Regel wenig bis garnichts zu tun ... 
Wenn du sowas hast, ist die Chamce groß, dass du einen Denkrehler hast.

Ausnahmen sind 2-Dimensionale Arrays, da geht es quasi nicht anders :)

von Johannes H. (Gast)


Lesenswert?

Zunächst mal vielen dank für die vielen Antworten. Mir ist schon klar, 
dass das Beispiel auch ohne einem Pointer geht, ich wollte eigentlich 
nur wissen wie man sowas löst weil es ist nicht so, dass sowas selten 
vorkommt...

Also gibt es dafür keine Lösung?

von Mampf F. (mampf) Benutzerseite


Lesenswert?

Johannes H. schrieb:
> Also gibt es dafür keine Lösung?

Stand doch da:

Beitrag "Re: Verständnis problem bei Pointer auf ein Pointer"


Oder meinst du etwas anderes?

: Bearbeitet durch User
von Dirk B. (dirkb2)


Lesenswert?

Johannes H. schrieb:
1
> void test (int * abc){
2
> 
3
>    *abc+ = 1;
4
>    return 0;
5
> }
6
> 
7
> int main(){
8
> 
9
>    int a = 0;
10
>    int * ptest = NULL;
11
>    ptest =  &a;
12
> 
13
>    test(&ptest)  //Da ist mein Verständnisproblem
14
> }
ptest ist vom Typ int*

test erwartet einen Paramter vom Typ int*

Es sind dieselben Typen, also muss da gar nichts gemacht werden.
1
    test(ptest)  // kein Adressoperator

von Johannes H. (Gast)


Lesenswert?

Ich habs endlich verstanden :)

Also solchen Funktionen wie strcpy kann ich einfache POinter, wie im 
obigen Beispiel angegeben, zuweisen, aber sobald ich einen Pointer auf 
POinter zuweise (sprich **pTtest) bekomme ich die WArnnung:
1
char expected 'char *' but argument is of type 'char **['/c]
2
3
ist ja klar jetzt habe ich ein **ptest und die FUnktion erwartet sich aber nur ein *ptest. 
4
5
Jetzt nur noch zum Verstehen: 
6
7
[c]
8
9
int main (){
10
11
char Buf[10];
12
13
char *pTest = Buf;
14
15
char *pTest1 = pTest;      //ab hier zeigen beide POinter auf das erste Element von Buf oder?

von Dirk B. (dirkb2)


Lesenswert?

Johannes H. schrieb:
> //ab hier zeigen beide POinter auf das erste Element von Buf oder?

Ja.

von Mampf F. (mampf) Benutzerseite


Lesenswert?

Johannes H. schrieb:
> ist ja klar jetzt habe ich ein **ptest und die FUnktion erwartet sich
> aber nur ein *ptest.

Jau genau ... Deshalb meinte ich vorher, mit ** wird man so gut wie nie 
arbeiten müssen.

Außer es sind 2D-Arrays, aber da würde man dann eher sowas machen:

void foo(char myarray[64][])

dann kann man innerhalb foo auch mit myarray[y][x] arbeiten.

Im Grunde ist aber char myarray[64][] nichts anderes wie ein char**

von Dirk B. (dirkb2)


Lesenswert?

Mampf F. schrieb:
> Im Grunde ist aber char myarray[64][] nichts anderes wie ein char**

Doch, ist es.

Und bei Arrays kann man beim ersten Index die Größe weglassen, nicht 
beim letzten.

von Mampf F. (mampf) Benutzerseite


Lesenswert?

> Und bei Arrays kann man beim ersten Index die Größe weglassen, nicht
> beim letzten.

Ups ja stimmt, sorry^^

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
Noch kein Account? Hier anmelden.