Wie kann ein gemischter Datentyp (int, float, char usw.) in einem Array gespeichert werden?
Möchte ich zum speichern gemischter Datentypen in einem array. Wie könnte man das machen?
Kommentar zu dem Problem
Es ist möglich und es gibt Anwendungsfälle, aber das ist wahrscheinlich an einem fehlerhaften design. Das ist nicht das, was arrays sind.
InformationsquelleAutor der Frage chanzerre | 2013-09-02
Du musst angemeldet sein, um einen Kommentar abzugeben.
Können Sie die array-Elemente einen besonderen union, aka tagged union.
Den
type
Mitglied wird verwendet, um halten Sie die Wahl, welches Mitglied derunion
ist, sollte verwendet werden, für jedes array-element. Also, wenn Sie speichern möchten, eineint
in das erste element, das Sie tun würden:Wenn Sie möchten, um Zugriff auf ein array-element, müssen Sie zunächst überprüfen Sie den Typ, dann verwenden Sie das entsprechende Mitglied der union zu werden. Ein
switch
- Anweisung ist nützlich:Es ist der Programmierer überlassen, um sicherzustellen, dass die
type
Mitglied entspricht immer dem letzten gespeicherten Wert in derunion
.InformationsquelleAutor der Antwort Barmar
Verwenden Sie eine union:
Haben Sie zu verfolgen, der Typ der jedes element, obwohl.
InformationsquelleAutor der Antwort
Array-Elemente müssen die selbe Größe haben, das ist, warum es nicht möglich ist. Man könnte es umgehen, durch die Schaffung einer variant-Typ:
Die Größe der element der union ist die Größe des größten Elements, 4.
InformationsquelleAutor der Antwort
Gibt es einen anderen Stil zu definieren: - tag-union (unter welchem Namen auch immer) , IMO ist es viel schöner zu verwenden, durch das entfernen der internen union. Das ist der Stil der X-Window-System für Dinge wie Ereignisse.
Beispiel in Barmar die Antwort gibt der name
val
auf die interne union. Das Beispiel in Sp.'s Antwort verwendet eine anonyme union zu vermeiden, geben Sie die.val.
jedes mal, wenn Sie Zugang zu der Variante record. Leider "anonyme" interne Strukturen und unions ist nicht verfügbar in C89 oder C99. Es ist eine compiler-Erweiterung, und daher bereits von Natur aus nicht tragbar.Einen besseren Weg, IMO ist zu invertieren, die ganze definition. Machen Sie jeden Daten-Typ seine eigene Struktur, und setzen Sie den tag (Typ Bezeichner) in jeder Struktur.
Dann wickeln Sie diese in ein top-level-union.
Nun kann es vorkommen, dass wir uns selbst zu wiederholen, und wir sind. Aber Bedenken Sie, dass diese definition wahrscheinlich ist, um isoliert werden zu einer einzigen Datei. Aber wir haben eliminiert den Lärm der Bestimmung der intermediate
.val.
bevor Sie an die Daten.Stattdessen geht es am Ende, wo es weniger widerlich. 😀
Andere Sache, die dies ermöglicht, ist eine form der Vererbung. Edit: das Teil ist nicht standard C, aber verwendet eine GNU-Erweiterung.
Up-casting und down-casting.
Edit: Ein Punkt zu beachten ist, wenn Sie den Bau einer von diesen mit C99 bezeichnet Initialisierungen. Alle member-Initialisierungen sollten durch die gleiche union-Mitglied.
Den
.tag
Initialisierer ignoriert werden kann durch einen optimierten compiler, weil die.int_
Initialisierung folgt, dass Aliase den gleichen Datenbereich. Obwohl wir wissen, das layout (!), und es sollte ok sein. Nein, es ist nicht. Verwenden Sie die "interne" - tag statt (es überlagert das äußere tag, genauso wie wir wollen, aber nicht verwirren den compiler).InformationsquelleAutor der Antwort luser droog
Können Sie eine
void *
array, mit einem getrennten array vonsize_t.
Aber Sie verlieren die Informationen geben.Wenn Sie brauchen, um Daten nicht in irgendeiner Weise halten Sie einem Dritten array von int (wo die int ist ein Enumerationswert) Dann der code der Funktion, die wandelt je nach
enum
Wert.InformationsquelleAutor der Antwort dzada
Union ist der standard-Weg zu gehen. Aber Sie haben andere Lösungen als gut.
Ist tagged pointer. Das nimmt den Vorteil ausgerichtet-Speicher, wobei die niedrigen bits der Adressen sind immer null. Zum Beispiel in der 32-bit-Systeme, Zeiger auf int muss ein Vielfaches von 4 sein und die low-2 bits müssen 0 sein, daher können Sie es verwenden, um speichern Sie die Typ Ihrer Werte. Natürlich müssen Sie deaktivieren Sie die bits vor der Dereferenzierung Werte.
Wenn Sie können, stellen Sie sicher, dass die Daten 8-byte-ausgerichtet, Sie haben ein wenig mehr für den tag. Auf den meisten aktuellen 64-bit-Systeme die virtuelle Adresse noch 48 bit, daher die hohen 16 bits können auch verwendet werden als tags.
Dieser hat nur ein Nachteil, Sie brauchen mehr Speicher, wenn die Daten nicht überall gespeichert. Also in dem Fall die Art und den Umfang Ihrer Daten begrenzt ist, können Sie speichern Sie die Werte direkt in den Zeiger. Dies wurde in Chrome-V8-Motor, wo es überprüft, das am wenigsten signifikante bit der Adresse, um zu sehen, ob das ein Zeiger auf ein double-oder eine 31-bit-Wert mit Vorzeichen (sogenannte smi - small integer). Wenn es ein int, Chrome macht einfach ein arithmetischer shift rechts 1 bit, um den Wert, andernfalls wird der Zeiger dereferenziert.
In früheren Versionen von Mozilla Firefox Sie verwenden auch kleine ganze Zahl Optimierungen wie die V8, die 3 low bits zu speichern, die den Typ (int, string, object,...). Aber da JaegerMonkey Sie nahm einen anderen Pfad (Mozilla ' s Neue JavaScript-Wert-Darstellung). Der Wert ist jetzt immer gespeichert in einem 64-bit-double-precision-variable. Wenn die double ist eine normalisierte, kann es direkt verwendet werden, in den Berechnungen. Wenn man jedoch die hohen 16 bits von es sind alle 1s Kennzeichnen, die ein NaN, die low 32-bits wird die Adresse speichern (in einem 32-bit-computer) auf den Wert oder den Wert direkt, die restlichen 16 bit werden verwendet, um zu speichern, die Typ. Diese Technik wird als NaN-Boxen. Wenn Ihre wichtigsten Daten-Typ-floating-point -, das ist die beste Lösung und liefert sehr gute Leistung. In 64-bit-Maschinen, es kann auch verwendet werden, als die Adresse ist oft nur 48 bits, wie oben angegeben.
Lesen Sie mehr über die oben genannten Techniken: https://wingolog.org/archives/2011/05/18/value-representation-in-javascript-implementations
InformationsquelleAutor der Antwort phuclv