Unterschiedliche Strukturnamen mit gleichem Inhalt (optimale Funktionsübergabe?)



  • Die Referenz "&" outet dich als C++ler und damit als C Laie.

    irgendwie zusammenfassen

    gibt schon einen Hinweis: union

    Jedenfalls keine Makros, die benutzt kein vernünftiger C Entwickler (bzw. nur im äußersten Notfall und vor allen Dingen: selten, jedenfalls nicht als grundsätzliche Implementierung, so wie C-Laie DarkShadow44).

    Sind die substructs ähnlich bzw. sogar identisch (wie bei dir) könnte das dann so aussehen (der aufrufende Kontext übernimmt einen (den wichtigsten!) Teil der Separierung).
    Deine gesuchte Universal-Funktion sieht dann doch schon sehr einfach aus:

    typedef union {
        int Value;
        struct SubStruct1 {
            int Value;
        } SubStruct1;
    
        struct SubStruct2 {
            int Value;
        } SubStruct2;
    
        struct SubStruct3 {
            int Value;
        } SubStruct3;
    } T;
    
    void print( T *t )
    {
        printf("%d\n",t->Value);
    }
    
    int main()
    {
        T t;
        t.SubStruct1.Value = 1;
        print(&t);
        t.SubStruct2.Value = 2;
        print(&t);
        t.SubStruct3.Value = 3;
        print(&t);
    
        return 0;
    }
    

    http://ideone.com/nqgqvm



  • Danke für die Tipps 🙂

    Auf 'union' bin ich während meiner Suche auch ein paar mal gestoßen. Allerdings werden die Variablen gewisserweise zusammengefasst. Bei mir sollten die Variablen schon individuell bleiben, da jede SubStruct ihre eigenen Werte hat. Ich versuche quasi per Parameter einer Funktion zu sagen, in welcher Substruktur etwas verarbeitet werden soll.

    Als Übersicht:
    Hauptstruktur->Substruktur_1->SubSubstruktur->...->Variable

    Der Name 'Substruktur_1' kann variieren, aber die enthaltene Struktur (->SubSubstruktur->...->Variable) ist immer gleich. Ein Array wäre da sinnvoll gewesen, aber meine Struktur isr generiert, daher ist eine Änderung nicht empfehlenswert.
    Ich werde mal morgen schauen, ob ich eine Lösung finde.

    Wünsche euch allen noch einen guten Rutsch ins neue Jahr 😉



  • Wutz schrieb:

    Sind die substructs ähnlich bzw. sogar identisch (wie bei dir) könnte das dann so aussehen (der aufrufende Kontext übernimmt einen (den wichtigsten!) Teil der Separierung).

    Das ist doch was ganz anderes, und nichtmal sinnvoll.

    1. Die Struct darf laut TS nicht verändert werden
    2. Es klingt eher so als ob der TS den Code einfacher haben will. Mit der Union erzwingst du dass alle Sub-structs die selben Werte habe, das ist logisch etwas ganz anderes. Da könnte man sich die verschiedenen Substructs gleich sparen.

    @TS
    Was du eigentlich willst ist soetwas:

    struct SubStruct { 
    	int Value; 
    };
    
    typedef struct MainStruct { 
    
    	int test;
        struct SubStruct SubStruct1; 
        struct SubStruct SubStruct2; 
        struct SubStruct SubStruct3; 
    
    } MainStruct_t;
    
    void setSubStruct(SubStruct*s, int newValue)
    {
        s->Value = newValue;
    }
    

    Vorausgesetzt die SubStructs sind wirklich gleich. Aber dafür müsstest du die Struct abändern.
    Sonst fällt mir außer Makros nichts ein.

    C++ Version:

    template<typename T>
    void setSubStruct(T &s, int newValue)
    {
    	s.Value = newValue;
    }
    
    void main()
    {
    	MainStruct_t ms;
    
    	setSubStruct(ms.SubStruct1, 12);
    	setSubStruct(ms.SubStruct2, 24);
    }
    

    Das ist recht elegant.


  • Mod

    SBond schrieb:

    ...ok. also einen Mod bitten diesen Thread in das C++-Forum zu verschieben? Ein zweiten thread nachträglich zu eröffnen ist wohl nicht so toll.
    sorry war ja nicht böse gemeint 😞

    ???
    Welche Sprache soll es denn nun sein? Du musst doch wohl selber wissen, welche Sprache du hier sprechen möchtest, es kann nicht gleichzeitig C und C++ sein. Entweder soll das C sein und du hast versehentlich etwas auf C++ gesagt (Weil dein C nicht so gut ist); oder es soll C++ sein und du hast bewusst ins falsche Forum gepostet.



  • DarkShadow44 schrieb:

    Wutz schrieb:

    Sind die substructs ähnlich bzw. sogar identisch (wie bei dir) könnte das dann so aussehen (der aufrufende Kontext übernimmt einen (den wichtigsten!) Teil der Separierung).

    Das ist doch was ganz anderes, und nichtmal sinnvoll.

    1. Die Struct darf laut TS nicht verändert werden
    2. Es klingt eher so als ob der TS den Code einfacher haben will. Mit der Union erzwingst du dass alle Sub-structs die selben Werte habe, das ist logisch etwas ganz anderes. Da könnte man sich die verschiedenen Substructs gleich sparen.

    Du redest Unsinn. Du hast die Intention meines Vorschlages nicht verstanden.
    Nirgendwo wird bei mir der Ausgangs-struct-Typ geändert, der Frager will den Code einfacher haben, und genau das hat er auch bekommen.
    Wenn es um C geht überlasse bitte mir die Einschätzung, ob etwas sinnvoll ist.
    Ich habe von dir hier noch keine Beiträge gelesen, die tiefschürfende C-Kenntnisse vermuten lassen.
    Also, wer lesen kann ist klar im Vorteil.
    Und da es offensichtlich auch für langjährige Forumsleser schwierig zu sein scheint, meinen Vorschlag eben als solchen zu betrachten (der einen prinzipiellen Lösungsweg vorschlägt) und stattdessen unsinnige Annahmen getroffen werden, was mein Beispielcode wohl tut, hier mal die weitergeführte Vorschlagslösung als Komplettlösung:

    typedef struct MainStruct {
    
        struct SubStruct1 {
            int Value;
        } s1;
    
        struct SubStruct2 {
            int Value;
        } s2;
    
        struct SubStruct3 {
            int Value;
        } s3;
    
    } MainStruct_t;
    
    typedef union {
        struct SubStruct1 *s1;
        struct SubStruct2 *s2;
        struct SubStruct3 *s3;
        int Value;
    } T;
    
    void setValue( T **t, int i )
    {
      (*t)->Value=i;
    }
    
    int main()
    {
        MainStruct_t x;
        T t;
    
        setValue( (t.s1=&x.s1,&t), 1);
        setValue( (t.s2=&x.s2,&t), 2);
        setValue( (t.s3=&x.s3,&t), 3);
    
        printf( "%d %d %d",x.s1.Value,x.s2.Value,x.s3.Value);
    
        return 0;
    }
    

    http://ideone.com/BNnH5t

    Und bevor du gleich antwortest, es läge hier UB vor weil dein Compiler was von incomp. pointertypes erzählt, befrage zuvor dein tiefschürfendes C-Wissen, was dir dann antworten wird, dass dem nicht so ist.



  • @Wutz
    Zwei Fragen zu deinem Code:

    1. Wieso zum Geier compiliert das? &t müsste ein T* sein, wie kann man das dann an eine Funktion übergeben die nen T** Parameter hat?
    2. Bist du sicher dass das keine strict-aliasing Verletzung ist? Gibt es in C da ne Ausnahme für Zeigertypen oder wie geht das?

    Der Code ist für mich als "habe ursprünglich mal C gelernt" C++ Programmierer auf jeden Fall überhaupt nicht leicht nachvollziehbar. Mag sein dass es in C nicht ganz ganz unüblich ist so zu schreiben, aber ich finde es grässlich. GRÄSSLICH.

    Und nochwas: Angenommen laut Standard ist hier alles A-OK. Dann müsstest du es immer noch erklären wenn du es einem Anfänger vorschlägst. Also warum es OK ist und in welchen Fällen man es machen darf und in welchen nicht. Sonst schadet ein solcher Vorschlag vermutlich viel viel mehr als er hilft.



  • Hallo Leute und ein frohes neues Jahr.

    vielen Dank für die Zahlreichen Antworten :).

    @SeppJ: Ja ich hätte es im C++-Forum stellen sollen. Ich war etwas unsicher wo ich den Thread erstelle und habe wohl die falsche Entscheidung getroffen. Sorry, das war keine böse Absicht.

    Die Lösung von Wutz habe ich noch nicht ganz verstanden, bzw. die Zeile "setValue( (t.s1=&x.s1,&t), 1);" konnte ich noch nicht ganz nachvollziehen. Ich muss erstmal wieder einen klaren Kopf von gestern haben und melde mich heute abend nochmal. Aber erstmal vielen Dank euch allen, dass ihr mit helft :).

    viele Grüße,
    SBond



  • Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C (alle ISO-Standards) in das Forum C++ (alle ISO-Standards) verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • So hier bin ich wieder.

    @SeppJ: Danke, dass du diesen Thread verschoben hast 🙂

    Habe mir nochmal den Code von Wutz angeschaut. Muss gestehen, dass ich mit der Zeile "setValue( (t.s1=&x.s1,&t), 1);" noch so meine Verständnisprobleme habe. So etwas habe ich auch noch nie gesehen, aber unter C funktioniert es schon mal ;). Wenn ich das richtig verstehe, referenzierst du mit Hilfe der union auf die Adresse der Substruktur in der MainStruct ("t.s1=&x.s1"). Ist schon clever. Aber was macht dieses '&t' noch im ersten Parameter? 😕

    Unter C++ läuft das Ganze nicht so ohne weiteres. Habe es irgendwie noch nicht hinbekommen und kriege als Fehler: "cannot convert ‘MainStruct::SubStruct1*’ to ‘SubStruct1*’ in assignment". Muss ich hier irgendwie noch ein cast im Parameter einsetzen?

    viele Grüße,
    SBond



  • Der Code von Wutz ist auch scheiße. Was soll dieser ganze Umweg über doppelt Dereferenzieren und die Union, wenn das den gleichen Effekt hat wie:

    int* p = (int*)&x.s1;  // Compiler dazu zwingen den Pointer auf unser struct zu einem Pointer auf ein int zu konvertieren
    *p = 1;
    

    Das funktioniert gerade noch wenn man einen int direkt am Anfang des structs setzen möchte (aber vermutlich auch nicht garantiert durch den Standard). Wenn es woanders steht braucht man weitere Anpassungen und wenn man structs hat wo der zu überschreibende Wert an verschiedenen Stellen steht hat man ganz verloren. Da du jetzt ja C++ zu programmieren scheinst verwende bitte die Lösung von DarkShadow44 mit Templates:

    template<typename T>
    void setSubStruct(T &s, int newValue)
    {
        s.Value = newValue;
    }
    
    void main()
    {
        MainStruct_t ms;
    
        setSubStruct(ms.SubStruct1, 12);
        setSubStruct(ms.SubStruct2, 24);
    }
    


  • sebi707 schrieb:

    Der Code von Wutz ist auch scheiße.

    Du hast keine Ahnung wovon du redest.



  • SBond schrieb:

    Muss gestehen, dass ich mit der Zeile "setValue( (t.s1=&x.s1,&t), 1);" noch so meine Verständnisprobleme habe.

    Tja, was soll man da machen?
    2 Hinweise mit lauffähigen Codes gegeben und du hast es immer noch nicht geschnallt.
    Man kann statt einem auch mehrere Objekte spendieren und die dann in deren Scope jederzeit verwenden, und kommt immer noch ohne irgendwelchen Makro- oder Template-Quatsch aus:

    int main()
    {
        MainStruct_t x;
        printf("%d %d %d\n",x.s1.Value,x.s2.Value,x.s3.Value);
    
        {
            T t1={&x.s1},t2={.s2=&x.s2},t3={.s3=&x.s3};
    
            setValue( &t1, 1);
            setValue( &t2, 2);
            setValue( &t3, 3);
        }
    
        printf("%d %d %d\n",x.s1.Value,x.s2.Value,x.s3.Value);
    
        return 0;
    }
    

    http://ideone.com/ds0bSP
    Das ist nun wirklich auch für C Laien verständlich, wenn du das auch nicht schnallst, such dir ein anderes Hobby.

    P.S. In jedem Fall musst du sicherstellen, dass das Padding der structs im Fremdmodul das Gleiche wie in deinem eigenen ist.



  • Wutz schrieb:

    sebi707 schrieb:

    Der Code von Wutz ist auch scheiße.

    Du hast keine Ahnung wovon du redest.

    Bitte demonstriere deinen Code für structs wo 'int Value;' nicht an erster Stelle steht. Und dann noch als Extra für structs wo Value in allen structs an verschiedenen Stellen steht.



  • hustbaer schrieb:

    Zwei Fragen zu deinem Code:

    1. weil du die Eigenschaft von union bzgl. des Member- und Gesamtzugriffs nicht verstanden hast
    2. da bin ich mir sehr sicher

    Nur weil du den Gebrauch von union nicht verstanden hast musst du nicht davon ausgehen, dass andere das auch nicht verstehen werden bzw. verstanden haben.
    Mit dem von mir gezeigten union-Gebrauch kann man komplette vtable-Hierarchien inkl. Mehrfachvererbung in blankem ANSI C nachbilden und das ist in jedem Fall besser als dem Anfänger irgendwelchen Makro/Template-Quatsch an die Hand zu geben und womöglich auch noch dynamic_cast und Konsorten nebst virtual-Quatsch zu zeigen mit dem Hinweis, dass so und nicht anders professionell C++ programmiert wird.
    In blankem ANSI C gibts bei solchen Versuchen, innerhalb der vtable-Nachbildung wild rumzucasten dann gleich was vom Compiler auf die Finger und nicht erst zur Laufzeit wie bei den C++-üblichen Unsinns-Casts.
    (Den Begriff vtable habe ich jetzt mal zur Veranschaulichung für dich gewählt, damit du einfacher den C-Hintergrund verstehen kannst; der kommt natürlich im C-Sprachgebrauch so nicht vor)



  • Dann erkläre mit bitte union. Ich programmieren zwar schon eine Weile aber vielleicht bin ich ja missinformiert. Für mich beduetet eine union das alle Member der union im gleichen Speicherbereich gespeichert werden. Allerdings hat der Compiler nach meinem Wissen keine Ahnung was für eine Variable ich dort wirklich gerade drin gespeichert habe. Wie man damit virtual Function Calls nachbilden können soll ist mir auch ein Rätsel.


  • Mod



  • Wutz schrieb:

    1. weil du die Eigenschaft von union bzgl. des Member- und Gesamtzugriffs nicht verstanden hast

    Aha.
    Super.
    Das hilft. 👍

    Nicht.



  • vielen Dank für eure Unterstützung.

    Sowohl die Lösung von Wutz, als auch von sebi707 funktioniert. Aber bitte keinen Streit anfangen. Ihr habt wahrscheinlich beide sehr gute Kenntnisse und jeder hat so seinen Stil und seine Vorzüge. Ich bin als Anfänger da noch sehr unvoreingenommen und ich frage nicht, weil ich zu faul bin selbst nach einer Lösung zu suchen. Das ich hier und da etwas noch nicht so schnell verstehe, ist nun mal leider so. Ich habe zuvor mit AutoIt, PureBasic und etwas C programmiert und daher ist es auch eine Phase der Umgewöhnung. ...gerade in Richtung OOP ist da vieles anders.

    Ich bin auf jeden Fall für jede Hilfe und Tipps dankbar, die ich hier bekomme und ich weiß es zu schätzen. Schließlich ist es ja auch eure Zeit und es steht euch frei zu Helfen.

    nochmals Danke an euch allen 😃

    Ich sehe somit die anfangs gestellte Frage als beantwortet 😉

    viele Grüße,
    SBond



  • In jedem Fall musst du sicherstellen, dass das Padding der structs im Fremdmodul das Gleiche wie in deinem eigenen ist.



  • Hallo Wutz,

    dein Code funktioniert aber nur bei exakt gleichem Layout der Substrukturen.
    Hier ein Gegenbeispiel:

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct MainStruct {
    
        struct SubStruct1 {
        	int x;
        	int y;
            int Value;
        } s1;
    
        struct SubStruct2 {
        	int y;
            int Value;
            int x;
        } s2;
    
        struct SubStruct3 {
            int Value;
            int x;
            int y;
        } s3;
    
    } MainStruct_t;
    
    typedef union {
        struct SubStruct1 *s1;
        struct SubStruct2 *s2;
        struct SubStruct3 *s3;
        int Value;
    } T;
    
    void setValue( T **t, int i )
    {
      (*t)->Value=i;
    }
    
    int main()
    {
        MainStruct_t x;
        T t;
    
        setValue( (t.s1=&x.s1,&t), 1);
        setValue( (t.s2=&x.s2,&t), 2);
        setValue( (t.s3=&x.s3,&t), 3);
    
        printf( "%d %d %d",x.s1.Value,x.s2.Value,x.s3.Value);
    
        return 0;
    }
    

    http://ideone.com/I9Wqg3

    Beispielausgabe:

    47 134513954 3
    

    Der Makro-Code oder die C++-Lösung mittels Template würde aber auch dann korrekt funktionieren (der Code vom OT bezieht sich ja nur auf den Zugriff auf die Membervariable 'Value').


Anmelden zum Antworten