Typkonvertierungsproblem



  • const ElementTyp (&Elemente)[Anzahl]

    Was passiert denn hier?
    Ich verstehe nicht was das im Cast-Operator soll.



  • Probier doch mal Type-Aliasing mit typedef, das macht die Sache uebersichtlicher:

    #include <stddef.h>
    
    typedef float Float3[3];
    typedef double Double3[3];
    
    template < class T >
    void SchreibeArray( const T* Quelle, size_t ArrayGroesse ) {
       T ArrayPuffer[100];
       for ( size_t i=0U; i < 100U && i < ArrayGroesse; ++i ) {
          ArrayPuffer[i] = Quelle[i];
       }
    }
    
    // ...
    
    void func( void ) {
       size_t   arrayGroesseN = 100U;
       Float3*  meineFloat3s  = reinterpret_cast<Float3* >( HoleVoidPtr() );
       Double3* meineDouble3s = reinterpret_cast<Double3*>( HoleVoidPtr() );
       SchreibeArray < Float3  > ( meineFloat3s , arrayGroesseN );
       SchreibeArray < Double3 > ( meineDouble3s, arrayGroesseN );
    }
    


  • sqrt(-1) schrieb:

    const ElementTyp (&Elemente)[Anzahl]

    Was passiert denn hier?

    Nichts. Das ist einfach ein Parameter.

    sqrt(-1) schrieb:

    Ich verstehe nicht was das im Cast-Operator soll.

    Cast-Operator? Was meinst du damit? Hier gibts keinen Cast-Operator.

    @Power Off
    Was soll das? Du verwirrst ihn doch nur noch mehr. Und funktionell ist dein Code auch nicht. Das einzig brauchbare ist

    void SchreibeArray( const T* Quelle, size_t ArrayGroesse )
    

    So würde man es machen, wenn auch dynamische Arrays möglich sind.



  • groovemaster schrieb:

    @Power Off
    Was soll das? Du verwirrst ihn doch nur noch mehr. Und funktionell ist dein Code auch nicht. Das einzig brauchbare ist

    void SchreibeArray( const T* Quelle, size_t ArrayGroesse )
    

    So würde man es machen, wenn auch dynamische Arrays möglich sind.

    Hmmm ... mein Vorschlag basiert auf den Hinweisen, die er auf sein Problem gegeben hat. Er hat Daten in der Form

    double x[N][3];
    float y[N][3]; 
    // usw., wobei N beliebig ist
    

    Deshalb meine Typedefs mit "Float3", "Double3", da immer ein Tupel komplett adressiert werden kann.

    Seine Funktion HoleVoidPtr() liefert die Adresse auf das naechste Array, das ich mittels reinterpret_cast<> auf jeweils einen Pointer-Typ auf Tupel-Typ X gecastet habe.

    Seinen Wunsch, template-Funktionen zu benutzen, habe ich durch die Funktion SchreibeArray<T>() abgebildet, die als Parameter den Tupel-Typ enthaelt und Pointer sowie Array-Groesse als Parameter nimmt. Da N beliebig, muss die Array-Groesse parametrisierbar sein.

    SchreibeArray<T>() ist nur eine Dummy-Implementation, da er ja sicherlich was anderes damit machen will als die Daten in temporaeres Array zu schreiben.



  • Erst einmal ein "Danke" für Euer Bemühen.

    Allerdings sehe ich nun wirklich nicht mehr durch in all den Vorschlägen.

    Was ich brauche, ist eine Template-Funktion die einen Zeiger annimmt.
    Die verschiedenen Typen sind auf die der Zeiger zeigt sind z.B.:

    float[3]
    short
    byte[4]
    ...

    Für den ersten Typ, währe also ein Element von der Größe 3*sizeof(float).

    (Die Template-Funktion muss dann noch die Byte-Offsegröße zwischen den einzelnen Elementen und die Anzahl an Elementen als Parameter annehmen.
    Dann ließt die Funktion alle Elemente entsprechend des Byte-Offsets und der Anzahl in einen Puffer und speichert diese in eine Datei.)

    Mein Problem ist es nun möglichst elegant die entsprechenden Zeiger zu kreieren und eine Template Funktion zu schreiben, die mit den verschiedenen Typen umgehen kann.
    Damit die Template-Funktion möglichst schlank wird, möchte ich gleich mit ganzen Elementen hantieren und nicht mit einzelnen primitiven Datenelementen eines Elements.

    Wenn über meine Frage noch etwas unklar ist dann bitte fragen. 😉

    Vielen Vielen Dank für Eure Hilfe!



  • Also ich habe es so wie gezeigt probiert.
    Wenn die Struktur, worauf der Zeiger zeigt, nur einen primitiven Datentyp behinhaltet, gibt es kein Problem.
    Wenn die Struktur ein Array enthält, stürzt das Programm mit dem Funktionsaufruf ab und führt nicht einmal eine Anweisung innerhalb der Template-Funktion aus.

    struct _AElement
    {
      short Element;
    }*APointer;
    
    struct _BElement
    {
      float Element[3];
    }*BPointer;
    
    APointer = (_AElement*)VoidPointer;
    LogArray(APointer, 45, 102);              // Alles Okay!
    
    BPointer = (_BElement*)VoidPointer;
    LogArray(BPointer, 55, 400);              // Absturz!
    
    template <class ElementType> DWORD LogArray(ElementType* ArrayPointer, int ArrayStride, int ArraySize)
    {
      ...
    }
    

    Bin echt ratlos.



  • Und noch einmal betreffs des Vorschlags von groovemaster:

    template <class ElementTyp, std::size_t Anzahl>
    void schreibeArray(const ElementTyp (&Elemente)[Anzahl])
    {
        ElementTyp ArrayPuffer[Anzahl];
        // wenn du einen Zeiger brauchst, dann ElementTyp* bla
    
        for (std::size_t i = 0; i != Anzahl; ++i)
        {
            ArrayPuffer[i] = Elemente[i];
        }
        //...
    }
    
    [...]
    
    // und der Aufruf
    float a[3];
    //...
    schreibeArray(a);
    

    Ich verstehe echt nicht was die Definition des Parameters für "schreibeArray(...)" da bedeutet.

    Danke für eure Hilfe!



  • Arrr...!

    Ich verzweifle hier - warum stürzt das ab, obwohl nicht einer Zeile in der Funktion abgearbeitet wird?



  • WOW!

    Folgendes:

    struct _AElement
    {
      short Element;
    }*APointer;
    
    struct _BElement
    {
      float Element[3];
    }*BPointer;
    
    APointer = (_AElement*)VoidPointer;
    LogArray(APointer, 45, 102);              // Alles Okay!
    
    BPointer = (_BElement*)VoidPointer;
    LogArray(BPointer, 55, 400);              // Absturz!
    
    template <class ElementType> DWORD LogArray(ElementType* ArrayPointer, int ArrayStride, int ArraySize)
    {
       LOGG("In der Template-Funktion");
    
       struct _LoggedArrays
       {
    	void* ArrayPointer;
    	DWORD FilePos;
       }LoggedArrays[1000];
    
       ElementType ArrayBuffer[100000];
    
       for(int i=0; i < 100000; i++)
       {
    	if(LoggedArrays[i].ArrayPointer == ArrayPointer) return LoggedArrays[i].FilePos;
    	if(LoggedArrays[i].ArrayPointer == 0)
            {
               LoggedArrays[i].ArrayPointer = FilePointer;
               ...
            }
        }
        ...  
    }
    

    Wenn das Array "ArrayBuffer" 100000 Elemente hat, fliege ich irgendwann einfach so raus - nicht einmal die LOGG("...")-Ausgabe wird geliefer!
    Die Parameter sind immer Okay!

    Reduziere ich die Array-Größe von ArrayBuffer auf eine kleinere Zahl (z.B. 100), gibt es keine Probleme!

    ElementType ist nie größer als 12 Byte!
    Was zum Teufel ist da los?



  • sqrt(-1) schrieb:

    Ich verstehe echt nicht was die Definition des Parameters für "schreibeArray(...)" da bedeutet.

    Was genau verstehst du denn nicht?

    template <class ElementTyp, std::size_t Anzahl>
    void schreibeArray(const ElementTyp (&Elemente)[Anzahl])
    

    Der Parameter beschreibt ein Array.
    - const bedeutet hier, dass wir nur lesenden Zugriff haben
    - ElementTyp ist, wie der Name schon sagt, der Typ eines Elements
    - Elemente ist der Bezeichner, über den man innerhalb der Funktion auf das Array zugreifen kann
    - in Anzahl steht überraschenderweise die Anzahl der Elemente im Array
    Hast du die Funktion überhaupt mal probiert?
    Wenn ich dich richtig verstanden habe, dann hast du simple 1-dimensionale Arrays, und nichts was Power Off mit 'double x[N][3]' geschrieben hat. Imo ist dann die Funktion von mir die einfachste Möglichkeit.

    sqrt(-1) schrieb:

    Wenn das Array "ArrayBuffer" 100000 Elemente hat, fliege ich irgendwann einfach so raus - nicht einmal die LOGG("...")-Ausgabe wird geliefer!
    Die Parameter sind immer Okay!

    Reduziere ich die Array-Größe von ArrayBuffer auf eine kleinere Zahl (z.B. 100), gibt es keine Probleme!

    Logisch, 'LoggedArrays' hat ja auch nur 1000 Elemente.



  • groovemaster schrieb:

    - Elemente ist der Bezeichner, über den man innerhalb der Funktion auf das Array zugreifen kann

    Und warum steht dieser in Klammerund und hat den Adressoperator davor?

    Hast du die Funktion überhaupt mal probiert?
    Wenn ich dich richtig verstanden habe, dann hast du simple 1-dimensionale Arrays, und nichts was Power Off mit 'double x[N][3]' geschrieben hat. Imo ist dann die Funktion von mir die einfachste Möglichkeit.

    Doch, ein Element ist eben 3*float.
    Und davon gibt es wiederum mehrere Elemente.

    sqrt(-1) schrieb:

    Wenn das Array "ArrayBuffer" 100000 Elemente hat, fliege ich irgendwann einfach so raus - nicht einmal die LOGG("...")-Ausgabe wird geliefer!
    Die Parameter sind immer Okay!

    Reduziere ich die Array-Größe von ArrayBuffer auf eine kleinere Zahl (z.B. 100), gibt es keine Probleme!

    Logisch, 'LoggedArrays' hat ja auch nur 1000 Elemente.

    Das habe ich nur falsch übernommen.
    In Wirklichkeit verwende ich auch die gleiche Größe.
    Und es passiert trotdem hin und wieder (mein "Programm" ist eine DLL).



  • sqrt(-1) schrieb:

    Und warum steht dieser in Klammerund und hat den Adressoperator davor?

    Das & steht hier nicht für AdressOf, sondern Referenz. Und warum das in Klammern stehen muss? Das kann ich dir auch nicht genau beantworten, das hat wohl was mit dem Typsystem von C++ zu tun.

    sqrt(-1) schrieb:

    Doch, ein Element ist eben 3*float.
    Und davon gibt es wiederum mehrere Elemente.

    OK, also 2-dimensionale Arrays. Wenn die in nativer Form vorliegen, zB

    float a[10][3];
    

    dann kannst du meine Templatefunktion trotzdem nutzen. Dann ist ein Element halt nicht vom Typ float, sondern 'float[3]'. Mit ein bisschen Meta-Programming kann man dann noch relativ einfach 'float' und '3' separieren.
    So wie ich dich verstehe, hast du aber lediglich einen Zeiger auf das erste Element. Also musst du auf die Variante von Power Off zurückgreifen

    void SchreibeArray( const T* Quelle, size_t ArrayGroesse )
    

    T wäre dann zB 'float[3]', und für 'ArrayGroesse' musst du halt die Anzahl der 'float[3]' Elemente angeben. Die musst du ja irgendwann mal spezifiziert haben.

    sqrt(-1) schrieb:

    Das habe ich nur falsch übernommen.
    In Wirklichkeit verwende ich auch die gleiche Größe.

    Das solltest du aber besser lassen. 8 Byte struct Grösse mal 100000 Elemente? Da kann dein Stack schon mal aufgebraucht sein. Besser du handelst sowas dann mit dynamischem Speicher.



  • groovemaster schrieb:

    Das & steht hier nicht für AdressOf, sondern Referenz. Und warum das in Klammern stehen muss? Das kann ich dir auch nicht genau beantworten, das hat wohl was mit dem Typsystem von C++ zu tun.

    Aber warum nimmst du da nicht einfach nur ein einfaches "Elemente" anstatt des "(&Elemente)"?

    void schreibeArray(const ElementTyp (&Elemente)[Anzahl])

    dann kannst du meine Templatefunktion trotzdem nutzen. Dann ist ein Element halt nicht vom Typ float, sondern 'float[3]'. Mit ein bisschen Meta-Programming kann man dann noch relativ einfach 'float' und '3' separieren.
    So wie ich dich verstehe, hast du aber lediglich einen Zeiger auf das erste Element. Also musst du auf die Variante von Power Off zurückgreifen

    void SchreibeArray( const T* Quelle, size_t ArrayGroesse )
    

    T wäre dann zB 'float[3]', und für 'ArrayGroesse' musst du halt die Anzahl der 'float[3]' Elemente angeben. Die musst du ja irgendwann mal spezifiziert haben.

    Ja, so brauche ich dies auch und habe es auch so implementiert.

    Das solltest du aber besser lassen. 8 Byte struct Grösse mal 100000 Elemente? Da kann dein Stack schon mal aufgebraucht sein. Besser du handelst sowas dann mit dynamischem Speicher.

    Auch wenn ich die Arrays auf dem Heap anlege stüzt das Programm wo ich die DLL nutze gelegentlich einfach so ab wenn ich die LogArray Funktion aufrufe.
    Das komische ist, dass sich dies nicht reproduzieren lässt.



  • sqrt(-1) schrieb:

    Aber warum nimmst du da nicht einfach nur ein einfaches "Elemente" anstatt des "(&Elemente)"?

    Weil es ohne Referenzen nunmal nicht funktioniert. Das liegt wohl daran, dass by-value übergebene Arrays nicht wirklich by-value gehandelt werden, sondern lediglich per Zeiger auf das erste Element.

    sqrt(-1) schrieb:

    Auch wenn ich die Arrays auf dem Heap anlege stüzt das Programm wo ich die DLL nutze gelegentlich einfach so ab wenn ich die LogArray Funktion aufrufe.
    Das komische ist, dass sich dies nicht reproduzieren lässt.

    Sowas ist immer schlecht, da es hier auch keinen Sinn macht, mit einem Debugger ranzugehen. Leider kann ich dir da auch nicht weiterhelfen, da dein Code einfach zu unvollständig bzw undurchsichtig ist. Das einzige was ich dir empfehlen kann, ist Exception Handling in Verbindung mit dem Laufzeit Debugging deines Compilers zu nutzen. Der aktuelle MS Compiler bietet hier zB relativ gute Möglichkeiten.


Anmelden zum Antworten