Variadic Function ohne Parameteranzahl



  • Wurstinator schrieb:

    Ach Mist, ich habs verwechselt und dachte cstring/cstdarg wären die C-Header 🙂

    @ CStoll: Bei diesem Konstruktor:

    template<unsigned int DIM, class VTYPE>
    Vektor<DIM, VTYPE>::Vektor(VTYPE vals[])
    {
        memcpy(values, vals, sizeof(vals) * sizeof(VTYPE));
    }
    

    wird aber nicht richtig kopiert, wenn ich nur sizeof(vals) nehme.

    An der Stelle kopierst du auch mit der Konstruktion die falsche Anzahl. Korrekter wäre dort DIM*sizeof(VTYPE) oder sizeof(values)

    Und zu welchen Problemen kann es mit einer eigenen Numerik-Klasse kommen? Weil der (Copy-)Konstruktor dann nicht aufgerufen wird?

    Genau so sieht's aus. Du brauchst dir nur mal eine BigInt-Klasse vorstellen, die ihren Wert in einem dynamisch verwalteten Array verstaut. Dann kopierst du per memcpy() die Innereien der Klasse und hast plötzlich zwei Objekte die beide der Meinung sind, sie hätten exklusiven Zugriff auf die dynamischen Daten.
    (und gerade im Umgang mit Templates kann es schneller als erwartet passieren, daß so ein Fall eintritt)


  • Mod

    non-POD + ellipse ist sowieso UB.



  • An der Stelle kopierst du auch mit der Konstruktion die falsche Anzahl. Korrekter wäre dort DIM*sizeof(VTYPE) oder sizeof(values)

    Wieso ist es denn richtiger, wenn ich mehr Werte kopiere, als der Quellarray hat?

    non-POD + ellipse ist sowieso UB.

    Was heißt UB?



  • Wurstinator schrieb:

    An der Stelle kopierst du auch mit der Konstruktion die falsche Anzahl. Korrekter wäre dort DIM*sizeof(VTYPE) oder sizeof(values)

    Wieso ist es denn richtiger, wenn ich mehr Werte kopiere, als der Quellarray hat?

    Auch wenn es sich gut tarnt, übergibst du dort kein Array, sondern nur einen Zeiger - und auf den angewendet gibt dir sizeof() keine praktisch verwertbare Angabe.



  • Wurstinator schrieb:

    Was heißt UB?

    Undefined behavior – undefiniertes Verhalten, also ein Bug der übelsten Sorte.



  • Auch wenn es sich gut tarnt, übergibst du dort kein Array, sondern nur einen Zeiger - und auf den angewendet gibt dir sizeof() keine praktisch verwertbare Angabe.

    Hä? Du hast doch ein paar Beiträge vorher gesagt, sizeof(vals) wäre die Größe des Arrays (in Bytes).

    Undefined behavior – undefiniertes Verhalten, also ein Bug der übelsten Sorte.

    Und warum ist das in diesem Fall so? oO



  • Wurstinator schrieb:

    Auch wenn es sich gut tarnt, übergibst du dort kein Array, sondern nur einen Zeiger - und auf den angewendet gibt dir sizeof() keine praktisch verwertbare Angabe.

    Hä? Du hast doch ein paar Beiträge vorher gesagt, sizeof(vals) wäre die Größe des Arrays (in Bytes).

    Da bin ich wohl mit deinem Bezeichnern durcheinandergekommen - sizeof() liefert die Größe des angegebenen Ausdrucks. Bei einem echten Array ist das dessen Gesamtgröße (Elementzahl*Elementgröße), bei einem Zeiger (inklusive "Array"-Parameter) idR 4 oder 8 je nach Betriebssystem.



  • Wurstinator schrieb:

    Hä? Du hast doch ein paar Beiträge vorher gesagt, sizeof(vals) wäre die Größe des Arrays (in Bytes).

    Zeiger und Array sind leicht unterschiedlich: sizeof(Ptr) liefert den Speicher des Zeigers zurück (auch wenn er auf ein Array zeigt) und sizeof(Arr) liefert den Speicher eines Elementes mal die Anzahl Elemente.

    EDIT: Mal wieder zu lahm 🙄



  • Und was ist ein "echter" Array?



  • Wurstinator schrieb:

    Und was ist ein "echter" Array?

    int EchtesArray[15];
    int* KeinEchtesArray = new int[15];
    int* AuchKeinEchtesArray = EchtesArray;
    


  • Du hast ein "echtes" Array dort in der Hand, wo du es als Array definiert hast. Dazu gehört z.B. der Klassenmember VTYPE values[DIM]; . Dort weiß der Compiler noch, daß er ein Array hat (und wie groß es ist), also kann er auch damit umgehen.


  • Mod

    unechte Zeiger? ganz ganz echte Arrays?

    Es ist viel einfacher:

    Zeiger, Arrays, Zeiger, Arrays... bitte nicht mit irgendwelchen Qualifikationen verwirren, die hier keinen Platz haben. Der Compiler macht ganz sicher nicht so feine Unterschiede.



  • camper schrieb:

    unechte Zeiger? ganz ganz echte Arrays?

    Es ist viel einfacher:

    Zeiger, Arrays, Zeiger, Arrays... bitte nicht mit irgendwelchen Qualifikationen verwirren, die hier keinen Platz haben. Der Compiler macht ganz sicher nicht so feine Unterschiede.

    Nur weil DU noch nie von echten und unechten Arrays gehört hast, heißt das noch lange nicht, dass es sie nicht gibt!



  • Also ein echter Array ist ein solcher, bei dem der Compiler die Größe kennt?

    void funktion(int array[]); // ein Zeiger
    void funktion(int array[3]); // ein Array?
    


  • Wurstinator schrieb:

    Also ein echter Array ist ein solcher, bei dem der Compiler die Größe kennt?

    Ja

    void funktion(int array[]); // ein Zeiger
    void funktion(int array[3]); // ein Array?
    

    Nein - das gehört zu den Erbschaften von C, daß hier die Größenangabe nicht beachtet wird und biede Funktionen einen Zeiger übergeben bekommen.



  • Manchmal mag man die Erbschaft so umgehen:

    template<unsigned int DIM, class VTYPE>
    Vektor<DIM, VTYPE>::Vektor(VTYPE (&vals)[DIM])//nur aufrufbar, wenn die Größe stimmt
    {
        memcpy(values, vals, sizeof(vals));//dann klappt's auch mit dem sizeof
    }
    


  • Oder man umgeht sie einfach, indem man keine Arrays benutzt. 💡



  • Nexus schrieb:

    Oder man umgeht sie einfach, indem man keine Arrays benutzt. 💡

    Erbschaft umgehen? Du solltest Dir eine andere Programmiersprache suchen!



  • Olga schrieb:

    Nexus schrieb:

    Oder man umgeht sie einfach, indem man keine Arrays benutzt. 💡

    Erbschaft umgehen? Du solltest Dir eine andere Programmiersprache suchen!

    Es gibt auch eine C++-Schule, die anfängt mit
    std::string filename("autoexec.bat");
    und nullterminierte char-arrays außerhalb string-Initialisierungen leugnet.
    Ich bin kein Freund davon. Aber es klappt. Und ist auch in vielerlei Hinsicht schneller, als zu fast allen Sprachen zu wechseln, die Strings als Sprachbestandteil haben.



  • Gewisse C-spezifische Dinge bringts schon. Zeiger und Makros zum Beispiel (ja, Makros). Aber bei Arrays, wo wir mit std::array die gleiche Funktionalität viel besser verpackt haben (Wertsemantik, keine implizite Zeiger-Konvertierung, STL-Interface, Assertions für Indexzugriff), sehe ich keinen Grund, an Antikem festzuhalten.


Anmelden zum Antworten