mikrocontroller.net

Forum: PC-Programmierung C-Funktion: externen Pointer verändern -> Pointer auf Pointer notwendig?


Autor: Ralf (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Hallo,

ich habe eine Verständnisfrage zu Pointern: wenn ich mit einer 
C-Funktion einen Pointer außerhalb der Funktion ändern möchte, dann darf 
die C-Funktion nicht einen "einfachen" Pointer als Parameter erwarten, 
sondern es muss ein Pointer auf einen Pointer sein, ist das korrekt?

Also anstatt:
uint8_t Arr_A[8];
uint8_t Arr_B[8];
uint8_t *PtrArr = Arr_A[0];

void A(uint8_t *Ptr) {
  Ptr = Arr_B[0];
}

int main(void) {
  A(PtrArr);
}
muss es lauten:
void A(uint8_t **Ptr) {  //Pointer auf Pointer
  *Ptr = Arr_B[0];
}

int main(void) {
  A(&PtrArr);               //Adresse des Pointers übergeben
}
weil der Pointer als Parameter selbst nur by-value übergeben wird. Im 
ersten Codeschnipsel würde demnach nur innerhalb der Funktion auf das 
zweite Array verwiesen, PtrArr selbst würde nicht geändert. Stimmt das 
so?

Wenn statt auf Arrays auf Structs verwiesen wird, deren Member selbst 
Pointer auf Arrays sind, würde es aber mit einfachen Pointern 
funktionieren, richtig?

Ralf

Autor: Heinz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja,
 aber Arr_B[0] ist kein Pointer sondern ein uint8_t, in dem Fall der 
Wert des 0ten Eintrags des Arrays Arr_B.

Lg

Autor: PuhBer (Gast)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Ralf schrieb:
> uint8_t Arr_A[8];
> uint8_t Arr_B[8];
> uint8_t *PtrArr = Arr_A[0];
>
> void A(uint8_t *Ptr) {
>   Ptr = Arr_B[0];
> }
>
> int main(void) {
>   A(PtrArr);
> }
void A(uint8_t *Ptr, uint8_t *otherPtr) {
  Ptr[0] = *(otherPtr + 3);
}

uint8_t Arr_A[8];
uint8_t Arr_B[8];

int main(void) {
  A(&(Arr_A[2], Arr_B);
}

Autor: Noch einer (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
> void A(uint8_t *Ptr, uint8_t *otherPtr) ???

Warum so kompliziert? Der Vorschlag von Heinz reicht doch vollkommen 
aus.
uint8_t Arr_A[8];
uint8_t Arr_B[8];
uint8_t *PtrArr = Arr_A;

void A(uint8_t **Ptr) {  //Pointer auf Pointer
  *Ptr = Arr_B;
}

int main(void) {
  Arr_B[0] = 42;
  A(&PtrArr);               //Adresse des Pointers übergeben
  printf("%d\n", (int) PtrArr[0]);
}

Autor: PuhBer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch einer schrieb:
> Warum so kompliziert?
Noch einer schrieb:
> void A(uint8_t **Ptr) {  //Pointer auf Pointer
>   *Ptr = Arr_B;

frage ich mich hier auch.

Da alle Variablen global sind, braucht es überhaupt keinen Parameter in 
der Funktion. ;-)
Wenn ich Inhalte des Array in der Funktion verändern möchte, brauche ich 
keinen zusätzlichen Pointer darauf. Also **Ptr ist bei der 
Aufgabenstellung *Ptr = Arr_B[0] blödsinn.

Autor: BlaBla (Gast)
Datum:

Bewertung
2 lesenswert
nicht lesenswert
PuhBer schrieb:
> blödsinn

Erstens schreibt man Blödsinn groß,
zweitens sind solche Worte unangemessen.

Autor: Noch einer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Aufgabenstellung *Ptr = Arr_B[0]

Was ist die Aufgabenstellung?

Möchtest du den Inhalt des Arrays in der Funktion verändern?
Oder soll nach dem Funktionsaufruf das PtrArr auf ein anderes Array 
zeigen?

> Da alle Variablen global sind...

Psst! Sonst bekommen wir bei der nächsten Frage ein sinnvolles, aber 
unüberschaubar grosses Beispiel.

Autor: PuhBer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich.moechte gar nichts verändern. Das steht so im Ausgangsposting.

Autor: c-hater (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ralf schrieb:

> ich habe eine Verständnisfrage zu Pointern: wenn ich mit einer
> C-Funktion einen Pointer außerhalb der Funktion ändern möchte, dann darf
> die C-Funktion nicht einen "einfachen" Pointer als Parameter erwarten,
> sondern es muss ein Pointer auf einen Pointer sein, ist das korrekt?

Nicht unbedingt. C erlaubt ja fast jeden Schmutz. Wenn man es aber so 
nutzt, dass man wenigstens die geringe Sicherheit des nur angedeuteten 
Typsystems nicht verletzt: Ja, dann ist es so, dann sollte ein Zeiger 
auf einen Zeiger übergeben werden.

Autor: Jobst Quis (joquis)
Datum:

Bewertung
-1 lesenswert
nicht lesenswert
Ralf schrieb:
> uint8_t *PtrArr = Arr_A[0];

Das ist großer Murks in mehrfacher Hinsicht.

Zum Einen, weil du damit einen Pointer mit einem Inhalt (uint8_t)
initialisieren willst. Korrekter wäre da:

uint8_t *PtrArr = Arr_A;

denn ein Array ist in C identisch mit einem Pointer auf das erste 
Element.

Aber auch das ist schlechter Stil, einen veränderlichen Pointer mit der 
Deklaration schon zu initialisieren. Denn es sollte vor einem Zugriff 
über einen Pointer klar sein, wohin dieser zeigt. Das ist mit einer 
expliziten Zuweisung im Programmablauf besser gewährleistet und besser 
sichtbar als in der statischen Deklaration.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Ralf schrieb:
> wenn ich mit einer
> C-Funktion einen Pointer außerhalb der Funktion ändern möchte, dann darf
> die C-Funktion nicht einen "einfachen" Pointer als Parameter erwarten

Doch, Du kannst auch einen Pointer zurückgeben, wird z.B. in der 
string.h sehr gerne gemacht.

Autor: MaWin (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Jobst Q. schrieb:
> denn ein Array ist in C identisch mit einem Pointer auf das erste
> Element.

Das ist nicht wahr. Identisch sind sie nicht. Es hängt vom Kontext ab, 
ob decay-to-pointer stattfindet.
#include <stdio.h>
int main(void)
{
        int a[10];
        printf("%d %d\n", sizeof(a), sizeof(&a[0]));
}

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.