Syntax: typedef struct



  • Skym0sh0 schrieb:

    JA! Endlich hab ich mal keinen Mist erzählt und Sone musste mich nicht korrigieren ! 😃

    Skym0sh0 schrieb:

    void main()
    

    😃



  • Ja C...



  • Skym0sh0 schrieb:

    Ja C...

    Seit wann ist es in c void main?



  • Fein,

    jetzt würde ich natürlich gerne Nutzcode reinpacken, in Verbindung mit Parallelisieren, schließlich ist das der Sinn und Zweck des Ganzen. 😃

    Also die wichtigsten Punkte sind: initialisieren, Anzahl an Threads bekanntgeben und seeden.

    mt_struct **mtss;    // (Struktur?) initialiseren?
    int count
    const int seed = 12;
    const int w = 32;
    const int p = 607;
    const double maxint = pow(2,w)-1;
    
    // Parameter für PRNG übergeben
    mtss = get_mt_parameters_st(w, p, 1, 8, seed, &count);
    
    // seeden
    for (i=0; i<count; i++)
    {
        sgenrand_mt(seed, mtss);
    }
    

    Jetzt kann ich im Rahmen von OpenMP ein paar Threads erzeugen und jeder einzelne ist in der Lage sich mit Zufallszahlen zwischen 0 und 1 zu versorgen

    #pragma omp parallel for 
      for(int in = 0; i < count; ++i)
        genrand_mt(mtss[i]) / maxint;
    

    Also jeder Thread [i]i* erzeugt seine Zufallszahlen, indem er auf den i. Eintrag von mtss zugreift.

    Jetzt würde ich in jeden Thread gerne Nutcode reinpacken, d.h. das Erzeugen einer Zufallszahl z.B. in eine (Klassen-) Funktion verpacken, die ich dann weiterreichen kann. Zur Initialisierung einer Klasse muss ich allerdings dieses ominöse mtss weitergeben. 😕

    Ich stelle es mir z.B. so vor:

    struct rng
    {
    	rng(double const, int i, (mt_struct**) &);
    
    	double const int_max;
    	int index_thread;
    	(mt_struct**) & my_mtss;
    
    	double operator() ();
    };
    
    rng::rng(double const int_max, int i, (mt_struct**) & mt):
    int_max(int_max),index_thread(i),my_mtss(mt)
    {}
    
    double rng::operator() ()
    {
    	return genrand_mt(mtss_mt[index_thread]) / int_max;
    }
    

    Aber diese Referenz auf dieses ominöse Pointer auf Pointer Objekt knirscht gewalt in der Ausführung. 😞

    Gruß,
    -- Klaus.



  • So,

    also folgendes funktioniert! 🕶

    #include <iostream>
    #include <math.h>
    
    #include <omp.h>
    
    extern "C"
    {
    	#include "dcmt0.6.1/include/dc.h"
    }
    
    struct rng
    {
    	rng(mt_struct** &, double const &);
    	mt_struct** & my_mtss;
    	int my_index;
    	double const & my_int_max;
    
    	double operator() (int & i);
    };
    
    rng::rng(mt_struct** & my_mtss, double const & my_int_max):
    my_mtss(my_mtss),my_int_max(my_int_max)
    {}
    
    double rng::operator() (int & i)
    {
    	return genrand_mt(my_mtss[i]) / my_int_max;
    }
    
    int main()
    {
    mt_struct** mtss;
    int count;
    int const seed = 18019182;
    int const w = 32;
    int const p = 607;
    double const int_max = pow(2,w) - 1;
    
    struct rng r(mtss,int_max);
    
    int N_threads = 8;
    
    // create N_threads MTs with IDs 1 ... N_threads --> count = N_threads
    mtss = get_mt_parameters_st(w, p, 1, N_threads, seed, &count);
    
    omp_set_num_threads(N_threads);
    
    // seed N_threads MT
    #pragma omp parallel for schedule (static,1)
    	for(int i = 0; i < N_threads; ++i)
    		sgenrand_mt(seed, mtss[i]);
    
    #pragma omp parallel for schedule (static,1)
    		for(int i = 0; i < N_threads; ++i)
    		{
    			std::cout << r(i) << std::endl;
    		}
    
    	// free MTs
    	free_mt_struct_array(mtss, N_threads);
    
    	return 0;
    }
    


  • mt_struct** & my_mtss;
    

    So etwas exotisches habe ich noch nie gesehen. Gerade als Member... 😮



  • Sone schrieb:

    mt_struct** & my_mtss;
    

    So etwas exotisches habe ich noch nie gesehen. Gerade als Member... 😮

    Du bist auch kein Three Star Programmer.



  • Was soll ich dazu sagen.

    Wenn ich eine Referenz haben nöchte, dann schaue ich mir an, wie das Objekt initialisiert wird und schreibe & dahinter.

    D.h. wenn dieses ominöse Objekt eben als Pointer auf Pointer initialisiert wird ... dann kommt eben solch eine Konstruktion heraus. 😕

    Gruß,
    -- Klaus.


  • Mod

    Klaus82 schrieb:

    D.h. wenn dieses ominöse Objekt eben als Pointer auf Pointer initialisiert wird ... dann kommt eben solch eine Konstruktion heraus. 😕

    Und deswegen wirst du hier 3-star Programmer "geschimpft". Je nach Sprache gehört um solch ein Monstrum mindestens eine, vielleicht auch mehrere, Abstraktionsschicht aus class, struct, typedef, Makro oder ähnlichem drumherum. Das macht Code kürzer, wartbarer, flexibler, lesbarer, verständlicher, und so weiter. Ich wage sogar zu sagen, dass dir als Programmierer vielleicht erst mit solch einer Abstraktion selber richtig klar wird, mit welcher Art von Objekt du hantierst und wie deine Funktionen dieses Objekt beeinflussen.



  • RealProgrammer schrieb:

    Du bist auch kein Three Star Programmer.

    Ich hatte einen Vorgesetzten, der sogar 5 Sterne-Programmierer war xD



  • Dreisterneprogrammierer ist man erst ab ***. Hier sehe ich kein Problem. Der Zeiger purzelt halt so aus der API raus, solange man damit außer drüber zu iterieren nichts weiter macht, kann der so bleiben.



  • asc schrieb:

    Ich hatte einen Vorgesetzten, der sogar 5 Sterne-Programmierer war xD

    Der Absatz Zeile ist als Rope-Ähnliches Array von Blöcken gebaut, haben wie schon char**, das Kapitel besteht aus Absätzen und der Text aus Kapiteln, char****, mehrere Tabs und char*****, und weil die FileOpen-Funktion das Array der Tabs vergrößern können muss, char******. Das programmier man natürlich heimlich mit Abstraktion und macht die dann kurz vor der Abgabe wieder weg.


  • Mod

    Bashar schrieb:

    Dreisterneprogrammierer ist man erst ab ***. Hier sehe ich kein Problem. Der Zeiger purzelt halt so aus der API raus, solange man damit außer drüber zu iterieren nichts weiter macht, kann der so bleiben.

    Stimme ich nicht zu. Referenzen auf Doppelzeiger sind drei Sterne, mit anderen Mitteln. Hier soll das Doppelzeigerkonstrukt wohl eine Art Typ sein, der eben by reference an die Funktion übergeben wird. Selbst auf niedrigstem Abstraktionsniveau ist hier doch mindestens ein typedef mt_struct** my_object_type; angesagt. Das kostet nichts und bringt so viel.



  • Und davon verschwindet der Zeiger? Was soll das bringen? Der einzige Effekt ist, dass jemand, der die API auch kennt, sich in dem Code nicht mehr ohne zusätzliche Denkarbeit zurechtfindet.



  • SeppJ schrieb:

    Und deswegen wirst du hier 3-star Programmer "geschimpft". Je nach Sprache gehört um solch ein Monstrum mindestens eine, vielleicht auch mehrere, Abstraktionsschicht aus class, struct, typedef, Makro oder ähnlichem drumherum.

    Also eine Art wrapper , wenn ich den Begriff in diesem Zusammenhang richtig deute?

    Gruß,
    -- Klaus.


  • Mod

    Bashar schrieb:

    Und davon verschwindet der Zeiger?

    Ja! Es geht doch nicht da drum, nötige Indirektionen los zu werden. Falls die Indirektion unnötig wäre, wäre das natürlich noch viel schlimmer.

    Was soll das bringen?

    Übersicht, Lesbarkeit, Wartbarkeit.

    Der einzige Effekt ist, dass jemand, der die API auch kennt, sich in dem Code nicht mehr ohne zusätzliche Denkarbeit zurechtfindet.

    Nein, ich meine ja auch auf dem Niveau der API. Solch ein Konstrukt sollte bei der Benutzung niemals vorkommen. Das typedef sollte von der API kommen.
    Da kann natürlich klaus82 nichts dafür, wenn die Fremdbibliothek mit solchen komischen Objekten hantiert. Die Beschuldingung der 3-Sterne-Programmierung rührt daher, dass ihm das ganz normal vorkommt und er keine andere Möglichkeit sah.

    klaus82 schrieb:

    Also eine Art wrapper, wenn ich den Begriff in diesem Zusammenhang richtig deute?

    Ja, genau das.



  • SeppJ schrieb:

    Nein, ich meine ja auch auf dem Niveau der API.

    Ihr meint mit API ein application programming interface, also Schnittstelle, ja?

    Dann werde ich mal wieder suchen, denn scheinbar soll solch ein wrapper die Resourcen ganz souverän verwalten, d.h. in meinem Falle initialisieren im Konstruktor, Speicher frei geben im Destruktor und dann eben die Regel der großen Drei beachten und weil es schon C++11 gibt, kann ich gleich den Move- und Assignment operator mitprogrammieren - eine gute Übung.

    Das ist der Fahrplan?

    Gruß,
    -- Klaus.



  • SeppJ schrieb:

    Bashar schrieb:

    Und davon verschwindet der Zeiger?

    Ja!

    Auch wenn mir das jetzt eventuell mitlesende Pascaller übelnehmen: Leute, die zwanghaft Zeiger wegtypedeffen, kann ich nicht ernst nehmen.

    Ich kann verstehen, dass manche sich davon überfordert fühlen. Aber niemand, der gleichzeitig die intellektuelle Kapazität hat, die neuesten Template-Tricks von C++11 nicht nur zu verstehen, sondern auch kreativ anzuwenden. Ich weiß nicht, was das Problem ist, aber ich bin auch kein Psychologe.

    Was soll das bringen?

    Übersicht, Lesbarkeit, Wartbarkeit.

    Das ist doch blabla.

    Nein, ich meine ja auch auf dem Niveau der API. Solch ein Konstrukt sollte bei der Benutzung niemals vorkommen. Das typedef sollte von der API kommen.

    Ach? Und wieso ist dann Klaus82 der Dreisterneprogrammierer, und nicht der Designer der API?


  • Mod

    Bashar schrieb:

    Was soll das bringen?

    Übersicht, Lesbarkeit, Wartbarkeit.

    Das ist doch blabla.

    😮 Dazu kann ich nichts mehr sagen. So etwas von dir? typedef ist Abstraktion allererster Güte, die kürzeren, fehlerloseren Code erlaubt, der zudem flexibler gegenüber Änderungen ist. Ohne jeden Nachteil! Wie kannst du das nicht erkennen?

    Ach? Und wieso ist dann Klaus82 der Dreisterneprogrammierer, und nicht der Designer der API?

    Habe ich doch gesagt. Eventuell hast du die Erklärung nicht gelesen, da ich sie erst ein paar Sekunden später reineditiert habe.



  • SeppJ schrieb:

    Bashar schrieb:

    Was soll das bringen?

    Übersicht, Lesbarkeit, Wartbarkeit.

    Das ist doch blabla.

    😮 Dazu kann ich nichts mehr sagen. So etwas von dir?

    Ja sicher. Denkst du, dass ich mich von drei hingeworfenen Wörtern beeindrucken lasse? Damit kann man jeden Schwachsinn begründen (und tut es in der Praxis auch, nach den Codierungsrichtlinien zu urteilen, die ich so gesehen habe.)

    typedef ist Abstraktion allererster Güte, die kürzeren, fehlerloseren Code erlaubt, der zudem flexibler gegenüber Änderungen ist. Ohne jeden Nachteil! Wie kannst du das nicht erkennen?

    Schon wieder nur blabla. Was wird denn da kürzer und fehlerloser? Was für Änderungen schweben dir vor? Du glaubst doch nicht wirklich, dass du nur das Typedef ändern musst, wenn die API geändert wird.

    Und siehst du nicht, dass das Teil sogar als Zeiger benutzt wird? Wieso willst du das Wesentliche wegabstrahieren? Das macht man eigentlich, um irrelevantes auszublenden, nicht weil man Angst hat, in Foren als Dreisterneprogrammierer beschimpft zu werden.

    Ach? Und wieso ist dann Klaus82 der Dreisterneprogrammierer, und nicht der Designer der API?

    Habe ich doch gesagt. Eventuell hast du die Erklärung nicht gelesen, da ich sie erst ein paar Sekunden später reineditiert habe.

    Äh ja, genau.


Anmelden zum Antworten