SOLVED: Array in Structs



  • Hallo Leute,

    folgendes Problem:

    Code funktioniert nicht:

    typedef struct TPoint{
       double x[3];
    }
    
    typedef struct TNode{
      TPoint P
      //und noch mehr
    }
    
    int main(){
      TNode* pNode = malloc(10 * sizeof(TNode));
      TNode* N;
      N = &pNode[0];
      N->P.x[0] = 1.0; //Fehler
      return 0;
    }
    

    So funktioniert der Code:

    typedef struct TPoint{
       double* x[3];
    }
    
    typedef struct TNode{
      TPoint P
      //und noch mehr
    }
    
    int main(){
      int i = 0;
      TNode* pNode = malloc(10 * sizeof(TNode));
      for(i=0;i<10;i++){pNode[i]->P.x = malloc(3 * sizeof(double));}
      TNode* N;
      N = &pNode[0];
      N->P.x[0] = 1.0; //Kein Fehler
      return 0;
    }
    

    Also, das Progamm ist wesentlich komplexer - aber das hier sollte das Problem veranschaulichen. Ich habe so das Gefühl, in der ersten Variante reserviert er den Speicher im Stack, so dass bei späteren Zugriffen nicht sicher gestellt ist, dass der Speicherbereich nicht verschoben wurde.
    Ich kann jetzt schon mit der funktionierenden Version weiter arbeiten, aber irgendwie kommt mir diese recht "unelegant" vor. Ich hätte schon gerne, dass die Punktkoordinaten von TPoint in einem Array liegen und dieses Array im Strucht integriert ist, welches ich auf dem Heap anlegen möchte.

    Irgend welche Ideen?

    Vielen Dank im Voraus,
    CJens


  • Mod

    Zu viel gekürzt. Problem ist nicht nachvollziehbar, nachdem man den Code ergänzt hat, bis er lauffähig ist. Deine Vermutungen sind jedenfalls vollkommener Quatsch, wenn man nur den derzeit gezeigten Code in Betracht zieht. Und dein zweiter Code ist noch viel größerer Quatsch, den kann ich nicht einmal so ergänzen, dass er compiliert oder auch nur irgendwie Sinn macht.
    Wie man Probleme nachstellbar und nachvollziehbar macht

    Ich hätte schon gerne, dass die Punktkoordinaten von TPoint in einem Array liegen und dieses Array im Strucht integriert ist, welches ich auf dem Heap anlegen möchte.

    Und wieso soll das Array nicht Teil des TPoint/TNode sein? Oder soll es das? Ich kann nicht nachvollziehen, was du möchtest.



  • Ok, scheine wohl irgendwo sonst etwas zu zerschießen.

    In dem Test funktionieren beide Codes:

    Code 1:

    typedef struct TPoint{
    	double x[3];
    }TPoint;
    
    typedef struct TNode{
    	TPoint P;
    	//und noch mehr
    }TNode;
    
    int main(){
    	TNode* pNode = malloc(10 * sizeof(TNode));
    	TNode* N;
    	N = &pNode[0];
    	N->P.x[0] = 1.0; //Fehler
    
    	getchar();
    	return 0;
    }
    

    Code 2:

    typedef struct TPoint{
    	double* x;
    }TPoint;
    
    typedef struct TNode{
    	TPoint P;
    	//und noch mehr
    }TNode;
    
    int main(){
    	int i = 0;
    	TNode* pNode = malloc(10 * sizeof(TNode));
    	for (i = 0; i<10; i++){ pNode[i].P.x = malloc(3 * sizeof(double)); }
    	TNode* N;
    	N = &pNode[0];
    	N->P.x[0] = 1.0;
    
    	getchar();
    	return 0;
    }
    

    Also Du sagst, dass im Fall 1 das Array im Struct TPoint liegt? Das will ich ja auch. Ich will nicht, dass die Daten total verteilt im Heap liegen.
    Meine Vermutung kam daher:

    double x[3]; //Speicher im Stack allociert - kann verschoben werden
    double* x = malloc(3*sizeof(double)); //Speicher im Heap allociert - ist statisch
    

    Ich werde mal den Zeiger auf x nach der Speicherallocierung und vor dem Zugriff checken und schauen, ob mir da irgend etwas anderes quer schießt.



  • Warum denn nicht einfach

    typedef struct TNode{
        double x[3];
        //und noch mehr
    }TNode;
    

    Auch hier liegt das Array direkt im struct und ist nicht "irgendwo im Heap verteilt".

    Wozu soll TPoint gut sein?



  • Hallo Sepp,

    danke für die Mühe - vergiss es. Ich bin über das TNode Array hinaus gelaufen. Das Probem war, dass ich die Daten nicht der Reihe nach einlese. Erstmal kommen die Daten von 1345 bis 5634, dann die DAten von 0 bis 1344, dann von 5635 bis 9576 usw. Dabei habe ich eine Schablone erwendet, in welcher nicht alles ganz richtig war.



  • Danke, so war es auch geplant. Das TPoint hat folgenden Sinn.
    In dem Programm gibt es Knoten mit x, y und z Koordinate. Es gibt aber auch Flächenelemente mit den Koordinaten des Mittelpunktes oder Volumenelemente mit den Koordinaten des Schwerpunktes.

    Wenn ich jetzt den Abstand eines Knotens zu einem Volumenelement-Schwerpunkt, oder von einem Flächenelement-Mittelpunkt zu einem Volumenelement-Schwerpunkt etc. berechnen will, muss ich für jede Paarung eine eigene Funktion schreiben. Wenn ich allerdings die Koordinaten alle über TPoint übergebe, dann kann ich alle Arten von Masterstructs miteinander verwursten, ohne für jedes Derivat eine eigene Funktion zu schreiben.


  • Mod

    CJens schrieb:

    Also Du sagst, dass im Fall 1 das Array im Struct TPoint liegt?

    So ist es. Im zweiten Fall ist alles kreuz und quer verteilt.

    Ich will nicht, dass die Daten total verteilt im Heap liegen.

    Es werden natürlich noch jeweils deine

    //und noch mehr
    

    zwischen den verschiedenen TPoints liegen. Der Aufbau im Fall 1 ist:

    -------------------------------------------------------------
    pNode -> zeigt auf | pnode[0] | pnode[1] | pnode[2] | ...  pnode[8] | pnode[9] |
                       -------------------------------------------------------------
                             |
                             | jedes pnode[i] besteht aus
                             v
     -----------------------------------------------
     |            P          |    und noch mehr    |
     -----------------------------------------------
                  |
                  | jedes P besteht aus
                  |
                  v
     -------------------------
     |            x          |
     -------------------------
                  |
                  | jedes x besteht aus
                  |
                  v
     -------------------------
     |  x[0] | x[1]  |  x[2] |
     -------------------------
    
    Also insgesamt zeigt pNode auf so etwas
    -------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    | pnode[0].P.x[0] | pnode[0].P.x[1] | pnode[0].P.x[2] | pnode[0].und_noch_mehr | pnode[1].P.x[0] | pnode[1].P.x[1] | pnode[1].P.x[2] | pnode[1].und_noch_mehr | ...     |
    -------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    

    Womit sich die Frage aufdrängt, was das x soll und warum du nicht einfach typedef double TPoint[3]; schreibst.

    N = &pNode[0];
    

    ist übrigens identisch zu

    N = pNode;
    


  • TPoint brauche ich öfters mal. Den Winkel zwischen drei Punkten bestimmen, den Abstand etc. weshalb ich TPoint als Struct definiert habe.

    TNode enthält einen TPoint (ist die Koordinate des Knoten)
    TElement enthält einen TPoint (die der Schwerpunkt des Elements)
    Jetzt will ich irgendwann den Abstand eines Knotens (TNode) zu dem Schwerpunkt eines Elements (TElement) bestimmen. Dafür ist TPoint gut.

    Die Frage war eigentlich:

    double x[3] //kann vom Betriebssystem verschoben werden, liegt auf dem Stack
    

    Gilt das auch, wenn ich das Array in einem statischen Struct auf dem Heap vorkommt oder ist damit diese Dynamik automatisch unterbunden?


  • Mod

    TPoint brauche ich öfters mal. Den Winkel zwischen drei Punkten bestimmen, den Abstand etc. weshalb ich TPoint als Struct definiert habe.

    Ich sehe nicht, wie der Gedankengang von "brauch ich öfters mal" zu "weshalb ich TPoint als Struct definiert habe" verläuft.

    CJens schrieb:

    Die Frage war eigentlich:

    Dann frag das doch gleich! Google: XY problem

    double x[3] //kann vom Betriebssystem verschoben werden, liegt auf dem Stack
    

    Gilt das auch, wenn ich das Array in einem statischen Struct auf dem Heap vorkommt oder ist damit diese Dynamik automatisch unterbunden?

    Kannst du mal Kontext liefern? Wo kommt diese Aussage her? Klingt nach ausgemachtem Unsinn.


Anmelden zum Antworten