Unterschiedliche Strukturnamen mit gleichem Inhalt (optimale Funktionsübergabe?)
-
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.
- Die Struct darf laut TS nicht verändert werden
- 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; }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:- 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?
- 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:
- weil du die Eigenschaft von union bzgl. des Member- und Gesamtzugriffs nicht verstanden hast
- 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.
-
-
Wutz schrieb:
- 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; }Beispielausgabe:
47 134513954 3Der 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').
-
SBond schrieb:
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.
Es sind hier nicht bloß verschiedene Stile. Der Code von Wutz ist der komplizierteste hier vorgeschlagene und funktioniert nur in den seltensten Fällen. Zumindest glaube ich das solange Wutz mir seinen Code nicht erklärt oder ein compilierbares Beispiel liefert, welches richtig funktioniert für structs wo Value an unterschiedlichen Stellen steht (siehe vorheriger Beitrag von Th69). Mich ärgert, dass Wutz einen solch verwirrenden Code einem Anfänger, der noch nicht zwischen einem unnötig komplizierten Code und einer cleveren Lösung für ein tatsächlich kompliziertes Problem unterscheiden kann, präsentiert.
hustbaer schrieb:
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?
Der compiliert aufgrund der laxen Konvertierungsregeln in C. In C kann ich einer Funktion, die ein Pointer auf ein int akzeptiert, auch ein Pointer auf ein double geben und alles was man kriegt ist eine Warnung. In C++ wäre das ein Fehler und ohne Cast compiliert der Code nicht. Ich nehme aber an, dass du das eh schon wusstest.
-
sebi707 schrieb:
Der compiliert aufgrund der laxen Konvertierungsregeln in C. In C kann ich einer Funktion, die ein Pointer auf ein int akzeptiert, auch ein Pointer auf ein double geben und alles was man kriegt ist eine Warnung. In C++ wäre das ein Fehler und ohne Cast compiliert der Code nicht. Ich nehme aber an, dass du das eh schon wusstest.
Ah, danke für die Erklärung. Und nein, wusste ich nicht mehr
(Also dass es in C++ ohne Cast nicht geht schon, darum ja die Frage - dass es in C implizit geht *brrr,schüttel* aber nicht.)Bleibt für mich aber immer noch die Frage warum das keine strict aliasing Verletzung sein soll. Bin mir nämlich ziemlich sicher dass es wohl eine ist.
-
sebi707 schrieb:
Der compiliert aufgrund der laxen Konvertierungsregeln in C. In C kann ich einer Funktion, die ein Pointer auf ein int akzeptiert, auch ein Pointer auf ein double geben und alles was man kriegt ist eine Warnung.
lol.
Wie niedlich.
Kommt vor, wenn sich C-Laien über C-Interna unterhalten und in C++ sowas dann regelmäßig wegcasten in der Meinung, so das Problem gelöst zu haben.