2009-05-10 6 views
5

Ich mag würde ein Array von Strukturen, mit dem gleichen Element wiederholtinitializng ein C-Array mit sich wiederholenden Daten

struct st ar[] = { {1,2}, {1,2}, {1,2} }; 

, dh initialisieren Jedoch habe ich für die keine Code ausführen wollen, wünsche ich, dass die Das Layout des Speichers bei der Ausführung des Programms wäre so, ohne dass irgendwelche CPU-Anweisungen involviert wären (dies würde die Boot-Zeit bei sehr langsamen CPUs und relativ großen Arrays erhöhen).

Dies ist sinnvoll, wenn das Array als Mini-Ad-hoc-Datenbank (Karten-ID zu Struct) verwendet wird und wenn ein Standardwert für alle Datenbankwerte verwendet werden soll.

Meine beste Lösung war etwas von der Form zu verwenden

#define I {1,2} 
struct st ar[SIZE_OF_ARRAY] = { I,I,I }; 

Damit wird der Compiler mich warnen, wenn ich zu viel mit bin oder zu wenig I s. Aber das ist alles andere als ideal.

Ich denke, es gibt keine Lösung für das in ANSI-C, aber ich dachte, dass es vielleicht eine Makro-Missbrauch oder GCC-Erweiterung, die die Arbeit machen würde. Idealerweise hätte ich gerne eine Standardlösung, aber auch Compiler-spezifische würden ausreichen.

Ich dachte, dass ich irgendwie in der Lage wäre, ein Makro rekursiv zu definieren, so dass I(27) würde zu 27 {1,2} s aufgelöst werden, aber ich glaube nicht, dass das möglich ist. Aber vielleicht irre ich mich, gibt es irgendeinen Hack dafür?

Vielleicht würde Inline-Montage den Trick machen? Es wäre sehr einfach, ein solches Speicherlayout mit MASM oder TASM zu definieren, aber ich bin mir nicht sicher, ob es möglich ist, Speicherlayout-Anweisungen in C-Code einzubetten.

Gibt es einen Linker-Trick, der es dazu verleiten würde, den Speicher entsprechend meinen Befehlen zu initialisieren?

PS I wissen Ich kann automatisch C-Datei mit einem Skript generieren. Die Verwendung von benutzerdefinierten Skripts ist nicht wünschenswert. Wenn ich ein benutzerdefiniertes Skript verwenden würde, würde ich ein C-Makro REP(count,exp,sep) erfinden und würde einen Mini-C-Präprozessor schreiben, um diesen mit exp sep exp sep ... exp {exp appears count time} zu ersetzen.

Antwort

10

Die boost preprocessor library (die für C gut funktioniert) könnte helfen.

#include <boost/preprocessor/repetition/enum.hpp> 

#define VALUE(z, n, text) {1,2} 

struct st ar[] = { 
    BOOST_PP_ENUM(27, VALUE, _) 
}; 

#undef VALUE 

Wenn Sie es benutzen wollen, müssen Sie nur das boost/preprocessor Verzeichnis von Boost - es enthielt vollständig selbst ist.

Obwohl es einige willkürliche Grenzen für die Anzahl der Elemente (ich denke, es ist 256 Wiederholungen in diesem Fall). Es gibt eine Alternative, die chaos genannt wird, die nicht, aber es ist experimentell und wird nur für Präprozessoren funktionieren, die dem Standard genau folgen (GCC's tut).

+0

Ja, BPP klingt ziemlich ideal für dieses Ding. – Macke

+0

Eine gute Standardlösung - danke. –

0

Was Sie in Form von I s haben, ist der beste Standard C kann Ihnen geben. Ich verstehe nicht, wie Sie Standard-Initialisierungscode ablehnen können, aber in Ordnung mit Assembly. Embedding Assembly ist notwendigerweise ein nicht standardmäßiger nicht tragbarer Mechanismus.

Das Problem mit rekursiven Makros ist, dass Sie nicht wissen würden, wo Sie aufhören sollen.

+0

Wie bereits erwähnt, kann das Hinzufügen von Initialisierungscode die Bootzeit verlangsamen. Inline-ASM ist jedoch schlecht, da es nicht Standard ist, aber es würde das genaue Verhalten, das ich von dem Code-Speicher wünsche, vorinitialisieren. Also, um es zusammenzufassen, ASM ist nicht portierbar, aber gibt das gewünschte Ergebnis, Initialisierungscode ist Standard - aber gibt ein anderes Ergebnis, das nicht immer akzeptabel ist. –

5

Der einfachste Weg, die ich denken kann ist, ein Skript zu schreiben, um die initialisers zu generieren, die Sie in Ihren C-Code enthalten kann:

{1,2}, 
{1,2}, 
{1,2} 

Dann in Ihrer Quelle:

struct st ar[] = { 
    #include "init.inc" 
}; 

können Sie Ordnen Sie Ihre Makefile, um dies automatisch zu generieren, wenn Sie möchten.

+0

Er spricht über C-Code. Ich sehe auch nicht, wie das besser ist, als die Initialisierer mit der Definition zu haben. Schließlich denke ich, er möchte die Initialisierungen basierend auf der Größe des Arrays automatisch generieren lassen. – dirkgently

+0

Dies kann automatisiert werden, wie Greg sagt. Vor allem, wenn Sie die Include-Datei init_3.inc für 3 Elemente, init_17.inc für 17 usw. aufrufen. Dann haben Sie eine Makefile-Regel, um init_ .inc für jedes n zu erstellen und Abhängigkeiten mit gcc -M oder -MM zu erzeugen. Also sagt die Quelle "struct st ar [] = {\ n #include" init3.inc "\ n};" und der Rest ist automatisch. –

2

Ich vermute, Sie können auf die Datei mit der Felddefinition, do:

#include "rep_array_autogen.c" 
struct st ar[SIZE_OF_ARRAY] = REPARRAY_DATA; 

und haben Ihr Makefile rep_array_autogen.c mit einem Format wie

#define SIZE_OF_ARRAY 3 
#define REPARRAY_DATA {{1, 2}, {1, 2}, {1, 2}, } 

erzeugen Da rep_array_autogen.c auf gebaut deine Maschine, es wäre genauso schnell wie die Hand darin.

0

Elazar,

Können Sie Daten geben Sie Ihre Ansicht zu unterstützen, dass vorinitialisiert Daten schneller als Laufzeit Initialisierung?

Wenn Sie Code auf einer Standardmaschine mit Festplatte (HDD) ausführen und Ihr Programm sich auf der Festplatte befindet, ist die Zeit zum Kopieren der Daten aus dem Datenabschnitt Ihres Binärbilds in den Arbeitsspeicher im Wesentlichen gleich Zeit als eine Art Laufzeitinitialisierung verwenden.

Kip Leitner

+1

Kip, ich gebe dir jetzt das rationale und die Daten später. Das rationale ist, mit nicht vorinitialisierten Daten kopiert der Loader das Binärbild, das die Information als Assemblerbefehle enthält (mov ax, Data). und dann müssen diese Assembly-Befehle erneut ausgeführt werden, um Daten in den Speicher zu verschieben. Was bedeutet Doppelarbeit. Ich werde versuchen, manchmal bald einen Mikro-Benchmark zu erstellen. –

Verwandte Themen