Pointer-Problem: Anfänger



  • Hallo,

    ich verstehe nicht wie ich ein double array füllen soll das ich über Pointer an eine funktion übergebe. Ich versuche es im Moment so:

    double *arr  = NULL;
    
    my_function(&arr);
    
    ...
    void my_function(doubl** arr)
    {
       //ich möchte z.B jetzt nur das dritte element setzen. dazu schalte ich 
       // den pointer fort:
       arr += 2;
    
       *arr = 7.9;
    
    }
    
    //muss ich denn das setzen so gestalten:?
    *arr[2] = 7.9; 
    
    //Wie kann ich denn einfach den pointer weiterschalten und dann ohne dass //ich eine indizierung habe den wert setzen?
    

    Noch ein Frage:
    Wenn ich das array fülle und den pointer immer weiterschalte - ist denn der pointer nach der prozedur immer noch am ende des arrays? Also zeigt er immer noch an das ende des arrrays oder steht er wieder am anfang?

    Danke



  • Also einmal: Pointer bleiben da, wo du sie hinweist, die tun nix von sich aus.

    Wenn du einen Pointer auf NULL setzt, dann verweist er auf kein Objekt, d.h. du darfst ihn nicht derefenzieren (=> auf den Wert des Objekts auf das der Pointer zeigt zugreifen).
    Wenn du jetzt ein double Array erstellen willst, machst du das so:

    double * arr = new double[10]; // legt ein double Array mit 10 Elementen an
    

    wenn du arr nicht mehr brauchst, musst du den Speicher mit delete[]freigeben, da sonst ein Speicherleck entsteht ...

    delete[] arr;
    

    Deine Funktion my_function kannst du wie folgt einbauen:

    void my_function(double * _arr) { 
    // ein einacher Pointer reicht, du übergibst einfach arr und nicht & arr an my_function, dann zeigen beide Pointer auf das gleiche objekt
    
      // Zugreifen auf das 3. Element kannst du nun wie folgt:
      _arr[2] = 7.9;
    }
    
    Aufrufen mittels:
    my_function(arr); // Adresse von arr wird nach _arr kopiert
    

    Willst du unbedingt die Pointer auf Pointer Sache mal ausprobieren:

    void my_function(double ** _arr) { 
      (*_arr)[2] = 7.9;
    }
    Aufrufen mittels:
    myfunction(&arr); // _arr bekommt die Adresse von arr zugewiesen
    

    Durch (*_arr) greifst du auf das Objekt auf das _arr verweist zu - da das Objekt, auf das _arr verweist, aber wieder eine Adresse ist, nimmst du den Indexoperator, um auf den Wert an der 3. Position zuzugreifen.



  • Danke für die Hile...

    leider verstehe ich so etwas immer noch nicht:

    nach my_function2() ist die länge nicht gesetzt wenn ich es so mache:

    Matrix *M;
    
    ...
    
    my_function(M);
    
    Class::my_function(Matrix *M)
    {
          my_function2(M);
    }
    
    Class::my_function2(Matrix *M)
     {
          M->setze_länge(4);
    }
    

    statt dessen funktioniert es so:

    Matrix *M;
    
    ...
    
    my_function(M);
    
    Class::my_function(Matrix *M)
    {
          my_function2(&M);
    }
    
    Class::my_function2(Matrix **M)
    {
          (*M)->setze_länge(4);
    }
    

    Kann mir das jemand erklären? warum funktioniert beispiel 1 nicht - da habe ich doch einen poiner auf die Matrix also müssste es doch klappen?



  • Hm, was meinst du mit "funktioniert nicht"?

    Ob du den pointer auf die Matrix nun per Wert (Version a) oder per Referen/pointer surchreichst, sollte eigentlich keinen nennenswerten Unterschied machen, eventuell wirds sogar so weit wegoptimiert, dass das selbe bei rauskommt...



  • Bei beispiel 1 gibt es einen segmentation fault....bei beispiel 2 nicht.

    Ich lege den pointer so an: Matrix* M = NULL;



  • also ich glaube das Problem liegt darin:

    [cpp]
    Matrix *M;

    ...

    my_function(M);

    Class::my_function(Matrix *M)
    {
    M = my_function2(M);
    M->set_length(4);
    }

    Matrix* Class::my_function2(Matrix *M)
    {
    M = New_Matrix();
    return M;
    }
    [/cpp]

    kann es sein dass durch die Methode New-Matrix() da irgendwas nicht passt - dort gebe ich einen Pointer zurück auf einen Heap-Bereich....



  • Ok also nochmals anders:

    Es ist ein triviales Problem bei dem ich nicht mehr durchblicke.

    Matrix * a = NULL;
    
    //pointer a wird initialisiert und zeigt auf etwas
    
    my_function(a);
    //auf len zugreifen löst segfault aus
    std::cout << a->lines->len << std::endl;
    
    //....
    void Class::my_function(Matrix *a)
    {
        my_function2(a);
    }
    
    //...
    void Class::my_function2(Matrix *a)
    {
          //Hier mache ich was mim pointer also greife
        //z.B auf Daten zu und verändere:
        a->lines->len = 4;
    }
    

    also irgendwas ist da falsch weil ich kann in der ausgangsfunktion als da wo my_function() aufgerufen wird nicht ohne einen seg-fault auf len zugreifen.

    Wenn ich statt dieser variante folgendes mache gehts - ist das so üblich wie ich es mache folgt?:

    Matrix * a = NULL;
    
    //pointer a wird initialisiert und zeigt auf etwas
    
    my_function(a);
    //auf len zugreifen geht
    std::cout << a->lines->len << std::endl;
    
    //....
    void Class::my_function(Matrix *&a)
    {
        my_function2(a);
    }
    
    //...
    void Class::my_function2(Matrix *&a)
    {
          //Hier mache ich was mim pointer also greife
        //z.B auf Daten zu und verändere:
        a->lines->len = 4;
    }
    

    oder ist das hier besser?

    Matrix * a = NULL;
    
    //pointer a wird initialisiert und zeigt auf etwas
    
    my_function(&a);
    //auf len zugreifen geht
    std::cout << a->lines->len << std::endl;
    
    //....
    void Class::my_function(Matrix **a)
    {
        my_function2(&a);
    }
    
    //...
    void Class::my_function2(Matrix **a)
    {
          //Hier mache ich was mim pointer also greife
        //z.B auf Daten zu und verändere:
        (*a)->lines->len = 4;
    }
    

    danke für eure Hilfe



  • Erstens: Ich hoffe doch, vor dem Zugriff (in der my_function2()) hast du etwas Speicher hinter dem Pointer angelegt, sonst gäbe es dort auch einen SegFault.

    Zweitens: Bei Variante 1 übergibst du eine Kopie des Zeigers, d.h. das globale 'a' bekommt gar nicht mit, wenn du in deinen Funktionen etwas zuweist. Bei Variante 2 und 3 (2 ist C++'iger ;)) übergibst du eine Referenz bzw. Zeiger auf dein globales 'a' und alle Aktionen wirken direkt durch.



  • Ich bin zwar selbst erst Anfänger in Sachen C++ aber ich werde das Gefühl nicht los, dass Du (Original-Poster) der Annahme unterliegst, ein Pointer (Zeiger) ist gleich dem Objekt, auf den er zeigen soll.

    int a = 12; <-- a ist eben ein int-Objekt mit dem Wert 12

    int *b = 12; <-- wäre ein Zeiger auf ein int-Objekt, welches (im Speicher) bei der Adresse 12 liegt.

    Die Dereferenzierung von Zeiger b: *b gibt dir also nicht 12, sondern den Wert der bei Adresse 12 liegt -> also was vollkommen undefiniertes.

    int *b = &a; <-- & ermittelt die Adresse (im Speicher) von a und diese wird dann b zugewiesen. Zu zeigt b nun auf a (im Speicher). Die Dereferenzierung *b gibt nun das gewünschte Ergebnis: 12.
    und haben für sich alleine soviel Aussagekraft wie
    Was für int-Objekte gilt, gilt für alle anderen auch.

    Pointer/Zeiger sind eigenständige Objekte/Variablen.

    Ich hoffe ich konnte ein bisschen aufklären. Korrigiert mich bitte, wenn ich falsch liege. 😉

    Regards...

    Heiko



  • int *b = 12; <-- wäre ein Zeiger auf ein int-Objekt, welches (im Speicher) bei der Adresse 12 liegt.

    du kannst doch keinen int einem int* zuweisen.....



  • int* 's sind intergale Werte, die dann implizit koncvertiert werden, wenn du sie einem int zuweist oder umgekehrt. geratenerweise wuerde die Ardesse (der Wert des pointers) nach obigem Ausdruck etwa so aussehen:

    0x0C000000 oder 0x0000000C (0x0C = hexadezimal 12)



  • pumuckl schrieb:

    int* 's sind intergale Werte, die dann implizit koncvertiert werden, wenn du sie einem int zuweist oder umgekehrt.

    In C++ werden Typen unterschiedlicher Indirektionsebenen nicht implizit konvertiert. In C++ werden nichtmal unterschiedliche Typen gleicher Indirektionsebene konvertiert (ausser die Konvertierung ist trivial, Bsp. short nach int). Nichtmal void* wird implizit in einen anderen Zeigertyp umgewandelt. Zum Glück.



  • Du hast vollkommen recht. Es funktioniert lediglich

    int a* = 0; // NULL ist z.B. in iostream mit 0 definiert

    Ersetze 12 im Bezug auf den Pointer durch 0 😉

    Das ändert jetzt aber auch nichts an der Kernaussage. Ein einsamer Pointer (z.B. Matrix * a = NULL) hat soviel Sinn wie ein Kubikmeter Luft bei 20°C. Wie die Poster vor mir schon bemerkten, kannst du den Pointer erst verwenden, wenn du ein konkretes Objekt hast, dessen Adresse du (bzw. der Pointer) kennst:

    Matrix mymatrix;
    Matrix* myptr_to_mymatrix = &mymatrix;

    oder

    Matrix* myptr_to_a_matrix = new Matrix; // <-- hier aber nicht das delete.. vergessen.

    nicht sinnvoll ist

    Matrix* myptr_to_a_matrix = NULL;

    wenn du kein konkretes Matrix-Objekt anlegst. Beim Aufruf von *myptr_to_a_matrix würde dein Programm versuchen auf ein Matrix-Objekt zuzugreifen, welches sich ab Adresse 0 im Speicher befindet (und da ist mit Sicherheit keins!).

    Grüße aus dem Sauerland...

    Heiko

    EDIT:

    Dein Anfangsproblem habe ich ganz aus den Augen verloren. Ich habe kurzerhand ein Beispielprogramm erstellt, welches (hoffentlich) annähernd deinem Problemfall entspricht.

    [cpp]#include <iostream>
    
    void fill_array(float* array, int array_length);
    void display_array(float* array, int array_length);
    
    int main(int argc, char** args)
    	{
    		const int arr_length = 20;
    		float array[arr_length];
    
    		fill_array(array, arr_length);
    		display_array(array, arr_length);
    
    		return 0;
    	}
    
    void fill_array(float* array, int array_length)
    	{
    		// Array mit 13.5 + i auffüllen
    		for(int i = 0; i < array_length; i++) {
    			array[i] = 13.5 + static_cast<float>(i);
    		}
    	}
    
    void display_array(float* array, int array_length)
    	{
    		// Array ausgeben
    		for(int i = 0; i < array_length; i++) {
    			std::cout << array[i] << " ";
    		}
    		std::cout << std::endl;
    	}	
    [/cpp]
    

    Kritik erwünscht.

    Grüße...

    Heiko



  • hm. wieder was gelernt.


Anmelden zum Antworten