typedef struct foo_s {
int a;
} foo;
typedef struct bar_s {
foo;
int b;
} bar;
Im Wesentlichen möchte ich tun:
bar b;
b.a;
Ich weiß, dass ich b.foo_name.a tun könnte, wenn ich die foo-Struktur in bar benannt hätte, aber ich würde es vorziehen, dies nicht zu tun.
Irgendeine Möglichkeit, dies zu tun?
Diese Frage hat eine Vielzahl unterschiedlicher Antworten erhalten, also lassen Sie mich die Notwendigkeit erklären. Der Grund, warum ich dies tun möchte, ist, dass ich eine Bibliothek habe, die ich an meine Situation anpassen muss, was bedeutet, dass ich die ursprüngliche Struct-Deklaration nicht ändern kann. Außerdem muss ich nur 1 Element am Anfang der Struktur hinzufügen (warum am Anfang?, weil ich eine ‘Objekt’-Struktur habe, die alle Strukturen im Projekt anführt). Ich könnte die Struktur einfach einbetten, wie Sie es erwähnen, aber es ist WIRKLICH ärgerlich, da alle Referenzen in „variable->image.location“ dieses „image“ eingegeben werden müssen. Eine Milliarde Typen getippt ist wirklich nervig.
Einige Compiler bieten genau dieses Verhalten als Erweiterung an. Ich persönlich denke, es birgt zu viel Risiko (Nesting structs sechs Schichten tief und ich vergesse, welche Namen Sie verwendet haben), also nenne ich nur das erste Mitglied _ – kurz, konsequent, abseits und nicht sonderlich umständlich. (Der Name könnte tatsächlich vom Standard und/oder Compiler reserviert sein, aber ich bezweifle, dass irgendjemand ihn verwenden würde, wenn dies der Fall wäre.)
– Chris Lutz
10. September 2011 um 8:56 Uhr
Wenn image ist lästig, viel zu tippen, verwenden img. Verwenden Sie Suchen und Ersetzen, um dies für Sie zu tun. Keine Sorge – was auch immer Sie tun müssen, Sie werden es überleben.
– Chris Lutz
10. September 2011 um 9:09 Uhr
@chacham15 Alter, vermeide es, eine C-Frage als C++ zu markieren. Das sind zwei völlig unterschiedliche Sprachen.
– amit kumar
10. September 2011 um 9:21 Uhr
Ja, ich habe das Etikett schnell entfernt
– chacham15
10. September 2011 um 10:00 Uhr
Sie müssen nicht verwenden foo_s für den Strukturnamen. typedef struct foo { ... } foo; funktioniert gut.
Es ist noch besser, wenn sie nehmen void * Zeiger und vermeiden Sie das Casting auf der Anruferseite. (Die Werte einiger Leute von „besser“ können sich von meinen unterscheiden.)
– Chris Lutz
10. September 2011 um 9:03 Uhr
Ja, es ist sicherlich bequemer für den Anrufer. Ich wollte zeigen, dass der Autor der foo-Funktionen nicht wissen muss, dass die “echte” Struktur etwas anderes als foo ist.
– Jouni K. Seppänen
10. September 2011 um 9:38 Uhr
Nun, beide Ansätze sind richtig und falsch zugleich. Die Typumwandlung zwingt den Client-Code zu einer geringen Qualität. Dies kann mit gelöst werden void *, aber das eliminiert die Typsicherheit, die noch schlimmer ist. Dennoch sind dies eine nette Antwort und einige gute Argumente, insbesondere Jounis letzter Kommentar, wenn es um Abstraktionen (den Vererbungspunkt) geht, aber die oben genannten Faktoren müssen berücksichtigt werden. Hier ist die C11-Lösung: modelingwithdata.org/arch/00000113.htm; Ich frage mich, ob es eine Problemumgehung für andere Versionen von C gab
– Machtsklave
2. Dezember 2013 um 17:06 Uhr
Nicht möglich im C so wie du es getan hast. Aber Sie können die Vererbung mit a nachahmen foo Mitgliedsvariable ein bar.
typedef struct bar_s {
foo obj;
int b;
} bar;
bar b;
b.obj.a = 10;
Ich denke, das hat der OP gemacht nicht wollen; es ist die “offensichtliche Lösung”.
– U. Windl
19. August 2021 um 12:28 Uhr
Kerl L
Wenn Sie meinen
typedef struct foo_s {
int a;
} foo;
typedef struct bar_s {
foo my_foo;
int b;
} bar;
also kannst du machen:
bar b; b.my_foo.a = 3;
Andernfalls gibt es seit dem keine Möglichkeit, dies in C zu tun sizeof(bar_s) ist nachteilig für die Kompilierzeit. Es ist keine gute Praxis, aber Sie können eine sparen void * ptr; Zeiger innerhalb von bar_s und eine weitere Aufzählung, die die beschreibt ptr Typ, und durch den Typ umgewandelt.
Sie müssen keine zusätzliche Datei erstellen, Sie können Strukturfelder mehrzeilig definieren
– Maxim Akristiny
29. Juni 2018 um 10:38 Uhr
Trotzdem ist diese Lösung etwas hässlich.
– U. Windl
19. August 2021 um 12:32 Uhr
@U.Windl Ja, Sie können auch einfach ein schnelles Skript schreiben, das “richtige” Strukturen generiert, die einfach dasselbe Speicherlayout verwenden … wären nicht mehr als ein paar Zeilen JavaScript, um alle Ihre erweiterten C-Strukturen zu generieren .
– kungfooman
19. August 2021 um 13:01 Uhr
Abraham Le
Es gibt eine Verwechslung zwischen anonymen Strukturen und Vereinigungen mit namenlosem Feld. Das namenlose Feld ist eine Microsoft-Erweiterung.
struct known {
struct /* anonymous */ {
int anonymous;
};
int known;
};
Ein anonymer struct oder union ist ein struct oder union ohne irgendetwas tag name das in ein anderes eingebettet ist struct oder union. Es muss auch keine Feldnamen haben.
Ein namenloses Feld ist eine Microsoft-Erweiterung, die eine eingeschränkte Vererbung in C ermöglicht.
struct A {
int a;
};
struct B {
struct A: // nameless field
int b;
};
Anonym struct oder union sind keine namenlosen Felder, und namenlose Felder sind nicht anonym, zumindest so, wie es der C11-Standard definiert.
Sie müssen keine zusätzliche Datei erstellen, Sie können Strukturfelder mehrzeilig definieren
– Maxim Akristiny
29. Juni 2018 um 10:38 Uhr
Trotzdem ist diese Lösung etwas hässlich.
– U. Windl
19. August 2021 um 12:32 Uhr
@U.Windl Ja, Sie können auch einfach ein schnelles Skript schreiben, das “richtige” Strukturen generiert, die einfach dasselbe Speicherlayout verwenden … wären nicht mehr als ein paar Zeilen JavaScript, um alle Ihre erweiterten C-Strukturen zu generieren .
– kungfooman
19. August 2021 um 13:01 Uhr
neudelphi
Sie können versuchen, die Vererbung zu verwenden:
struct foo_s
{
int a;
};
struct bar_s: foo_a
{
int b;
};
Funktioniert in C++, nicht sicher, ob es in C funktioniert.
mein schlechtes, du hast recht, ich weiß nicht, warum ich das c++-tag hinzugefügt habe, ich meinte c. sry!
– chacham15
10. September 2011 um 8:37 Uhr
Vererbung funktioniert in C AFAIK nicht. Ich vermute, das OP wollte genau den Vererbungsmechanismus von C++ in C nachahmen.
– U. Windl
19. August 2021 um 12:37 Uhr
12572500cookie-checkKann ich eine Struktur in C “erweitern”?yes
Einige Compiler bieten genau dieses Verhalten als Erweiterung an. Ich persönlich denke, es birgt zu viel Risiko (Nesting
struct
s sechs Schichten tief und ich vergesse, welche Namen Sie verwendet haben), also nenne ich nur das erste Mitglied_
– kurz, konsequent, abseits und nicht sonderlich umständlich. (Der Name könnte tatsächlich vom Standard und/oder Compiler reserviert sein, aber ich bezweifle, dass irgendjemand ihn verwenden würde, wenn dies der Fall wäre.)– Chris Lutz
10. September 2011 um 8:56 Uhr
Wenn
image
ist lästig, viel zu tippen, verwendenimg
. Verwenden Sie Suchen und Ersetzen, um dies für Sie zu tun. Keine Sorge – was auch immer Sie tun müssen, Sie werden es überleben.– Chris Lutz
10. September 2011 um 9:09 Uhr
@chacham15 Alter, vermeide es, eine C-Frage als C++ zu markieren. Das sind zwei völlig unterschiedliche Sprachen.
– amit kumar
10. September 2011 um 9:21 Uhr
Ja, ich habe das Etikett schnell entfernt
– chacham15
10. September 2011 um 10:00 Uhr
Sie müssen nicht verwenden
foo_s
für den Strukturnamen.typedef struct foo { ... } foo;
funktioniert gut.– 12Me21
2. November 2018 um 22:35 Uhr