Forum: Mikrocontroller und Digitale Elektronik Pointer in Funktion inkrementieren - Adress Frage


von UnderDog (Gast)


Lesenswert?

Moin,

habe da mal eine Frage bzgl. Pointern.
Ich übergebe der Funktion ja als "strDest", den Zielort oder Speicher.
Die Funktion kopiert mir also von "strSrc" -> nach "strDest".


Meine Frage.: Ich inkrementiere den Zeiger "strDest" in der Funktion, 
heißt das auch gleichzeitig
das ich die Adresse vom Zielspeicher inkrementiere?

Oder wie genau wird das gehändelt?

char buff[10] = "";

void strcpy_(char *strDest, const char *strSrc)
{
    while(*strDest++ = *strSrc++);
}

Wenn ich dem Parameter "strSrc" = "Hallo" übergebe, wird "strDest" doch 
6 mal inkrementiert oder?
Somit müsste mein "buff" doch jetzt inkremtiert werden?

Danke für die Erklärung.

von c-hater (Gast)


Lesenswert?

UnderDog schrieb:

> void strcpy_(char *strDest, const char *strSrc)
> {
>     while(*strDest++ = *strSrc++);
> }
>
> Wenn ich dem Parameter "strSrc" = "Hallo" übergebe, wird "strDest" doch
> 6 mal inkrementiert oder?
> Somit müsste mein "buff" doch jetzt inkremtiert werden?

Nein. Inkrementiert werden nur die funktionslokalen Kopien der Zeiger. 
Willst du wirklich den ursprünglichen Zeiger inkrementieren, mußt du 
nicht den Zeiger selber an die Funktion übergeben, sondern einen Zeiger 
auf die Zeigervariable (und natürlich den Rumpf der Funktion 
entsprechend anpassen).

von UnderDog (Gast)


Lesenswert?

Ah Okay.
Also werden jeweils noch Kopien in den Funktionen angelegt. Wusste ich 
noch nicht. Klingt aber logisch.

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

UnderDog schrieb:
> Also werden jeweils noch Kopien in den Funktionen angelegt. Wusste ich
> noch nicht. Klingt aber logisch.

Eigentlich werden keine Kopien angelegt... das Konzept nennt sich "call 
by value", und in C gibt es auch nur dieses (im Gegensatz zu zB Pascal)

von Pointerpointerpointer (Gast)


Lesenswert?

UnderDog schrieb:
> Ah Okay.
> Also werden jeweils noch Kopien in den Funktionen angelegt. Wusste ich
> noch nicht. Klingt aber logisch.

Wenn du den Pointer in einer Funktion inkrementieren willst, kannst du 
einen Pointer auf einen Ponter setzen und den der Funktion übergeben.

also:

TolleFunktion(int **ptr);

von Possetitjel (Gast)


Lesenswert?

Michael R. schrieb:

> Eigentlich werden keine Kopien angelegt...

Nun ja, wie würdest Du das nennen, was da auf den Stack
liegt?

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Possetitjel schrieb:
> Michael R. schrieb:
>
>> Eigentlich werden keine Kopien angelegt...
>
> Nun ja, wie würdest Du das nennen, was da auf den Stack
> liegt?

Hab mich unklar ausgedrückt: Die Funktion selbst legt keine Kopien an

von Possetitjel (Gast)


Lesenswert?

Michael R. schrieb:

>>> Eigentlich werden keine Kopien angelegt...
>>
>> Nun ja, wie würdest Du das nennen, was da auf den Stack
>> liegt?
>
> Hab mich unklar ausgedrückt: Die Funktion selbst legt
> keine Kopien an

Ja, okay. Hast Recht. Die Kopie wird natürlich beim
Aufruf der Funktion angelegt, nicht IN der Funktion.

von Dirk B. (dirkb2)


Lesenswert?

Alle Parameter einer C-Funktion sind Kopien.

Bei Arrays sind es halt die Anfangsadressen.

Die Funktionsparametern sind alles lokale Variablen.


Arrays kännen, nach ihrer Definition, weder in der Größe noch der 
Adresse geändert werden.

Darum würde das Beispiel mit buff auch nicht mit Doppelzeiger (Zeiger 
auf Zeiger) funktioniern.

von Pointerpointerpointer (Gast)


Lesenswert?

Dirk B. schrieb:
> Darum würde das Beispiel mit buff auch nicht mit Doppelzeiger (Zeiger
> auf Zeiger) funktioniern.

Warum?
Pointer sind nur Speicheradressen.

Ob in der Speicherstelle auf die die Adresse zeight wieder eine Adresse 
steht (Doppelpointer), die Adresse auf das erste Element eines Arrays 
zeigt oder in den Wald ist dabei völlig unerheblich.

Wenn da eine Adresse steht, kann man die auch verändern. Und das ist 
völlig legitim, der Compiler weiß duch die Deklaration auch genau, wie 
er daszu tun hat.

von M. S. (nickfisher)


Lesenswert?

Pointerpointerpointer schrieb:
> Dirk B. schrieb:
> Darum würde das Beispiel mit buff auch nicht mit Doppelzeiger (Zeiger
> auf Zeiger) funktioniern.
>
> Warum?
> Pointer sind nur Speicheradressen.
>
> Ob in der Speicherstelle auf die die Adresse zeight wieder eine Adresse
> steht (Doppelpointer), die Adresse auf das erste Element eines Arrays
> zeigt oder in den Wald ist dabei völlig unerheblich.
>
> Wenn da eine Adresse steht, kann man die auch verändern. Und das ist
> völlig legitim, der Compiler weiß duch die Deklaration auch genau, wie
> er daszu tun hat.

Einen pointer auf die anfansadresse des arrays kannst du natürlich 
verändern, ein array aber nicht.es wird zwar immer gern behauptet 
array=pointer aber das ist eben nicht immer wahr.

: Bearbeitet durch User
von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

UnderDog schrieb:
> Somit müsste mein "buff" doch jetzt inkremtiert werden?

Das ist genauso wie bei numerischen Argumenten:
1
void add42 (int value)
2
{
3
    value += 42;
4
    printf ("value=%d\n", value);
5
}
6
7
int main ()
8
{
9
    int x = 10;
10
11
    add42 (x);
12
    printf ("x=%d\n", x);
13
    return 0;
14
}

Das Programm wird für x auch nach Aufruf der Funktion add42() 10 und 
nicht 52 ausgeben. Eben, weil die Werte der Parameter kopiert werden. 
Anders ist es, wenn Du eine Referenz (also einen Pointer) übergibst:
1
void add42 (int *value)
2
{
3
    *value += 42;
4
    printf ("value=%d\n", *value);
5
}
6
7
int main ()
8
{
9
    int x = 10;
10
11
    add42 (&x);
12
    printf ("x=%d\n", x);
13
    return 0;
14
}

Hier wird der Pointer beim Aufruf kopiert. Dieser zeigt aber weiterhin 
auf den Speicherbereich, wo x abgelegt ist. Folglich hat die Variable x 
nach dem Funktionsaufruf nun den Wert 52.

von Dirk B. (dirkb2)


Lesenswert?

buff ist ein Array. Da gibt es keinen (loaklisierbaren) Speicherplatz, 
in dem die Adresse des Arrays abgelegt ist.
1
char buff[20];
2
char *pc;
3
4
//pc kannst du irgendwohin zeigen lassen, buff jedoch nicht.
5
6
void xxx (char **p) 
7
{ **p += 1;
8
}
9
10
xxx(&pc);  // geht
11
xxx(&buff); // geht nicht

von Dirk B. (dirkb2)


Lesenswert?

Simon S. schrieb:
> es wird zwar immer gern behauptet
> array=pointer aber das ist eben nicht immer wahr.

Das ist nie wahr.

Die Schreibweisen beim Zugriff ähneln sich.

von Jobst Q. (joquis)


Lesenswert?

UnderDog schrieb:
> Wenn ich dem Parameter "strSrc" = "Hallo" übergebe, wird "strDest" doch
> 6 mal inkrementiert oder?
> Somit müsste mein "buff" doch jetzt inkremtiert werden?

Nein, so nicht. Wenn du in der aufrufenden Funktion einen 
inkrementierten Zeiger haben willst, muss der zurückgegeben werden:

char * stpcpy_(char *strDest, const char *strSrc)
{
    while(*strDest++ = *strSrc++);
    return strDest;
}

char buff[20];
char *t;

t= stpcpy_(buff, "Hallo");
stpcpy_(t, " Welt!");
printf("%s\n",buff);

von Oliver S. (oliverso)


Lesenswert?

Die offizielle Formulierung lautet auf Englisch

> Die Schreibweisen beim Zugriff ähneln sich.

Ein Array „decays to“ = zerfällt in einen Pointer, wenn es als 
Funktionsparameter übergehen wird. Innerhalb der Funktion ist es ein 
Pointer, draußen ein Array.

Oliver

von Dirk B. (dirkb2)


Lesenswert?

Oliver S. schrieb:
> Ein Array „decays to“ = zerfällt in einen Pointer, wenn es als
> Funktionsparameter übergehen wird. Innerhalb der Funktion ist es ein
> Pointer, draußen ein Array.

Ganz so war das nicht gemeint.

Du kannst aus a[10] oder *b nicht erkennen, ob a oder b jeweils Pointer 
oder Array ist.

Aber beim sizeof, inkrement, Adressoperator, als Zuweisungsziel ist es 
ein großer Unterschied.

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.