Forum: PC-Programmierung C - halbwegs große, konstante Structures


von Walter T. (nicolas)


Lesenswert?

Hallo zusammen,
ich habe momentan das Problem, daß ich in C Structures mit zur 
Kompilierzeit bekannen Werten füllen muß. Momentan sieht das so aus:
1
#include "werte.h"
2
3
typedef enum {reich,
4
              stamm,
5
              klasse,
6
              ordnung,
7
              familie,
8
              gattung,
9
              art } viecher_t
10
11
12
typedef struct {
13
        const char*    name;       
14
        const char*    zeugs;      
15
        boolean        tot;
16
        unsigned int   beine;
17
        viecher_t      viech;
18
        double         masse;
19
     } Getier_t;
20
21
int main() {
22
   Getier_t Getier = GETIER;
23
24
   ...
25
}

und in der Headerdatei werte.h
1
#define GETIER {\
2
  {"Helmut","Huhn",false,2,gattung,1.000000e-001},\
3
  {"Mark","Hund",true,4,art,,1.500000e+001},\
4
  {"Margret","Paarhufer",false,3,familie,8.200000e+002},\
5
  {"Dirk","1/2 Haehnchen",true,1,familie,3.200000e-001},\
6
}
sodaß die Daten in die ausführbare Datei einkompiliert werden, was auch 
Ziel der Sache ist, da ich nicht auf externe Daten zugreifen kann und 
will.

Mache ich das Ganze allerdings mit ein paar Daten mehr (so 10000 
structure-Einträge) schießt die Kompilierzeit (hier mit dem MS 
VC-Compiler) ins unermeßliche (die .h-Datei ist so ca. 2MB groß und er 
kompiliert jetzt seit gut 40 Minuten).

Kennt jemand eine effiziente Möglichkeit, diese konstanten Structures 
mit Werten zu befüllen, daß am Ende trotzdem alles in einer ausführbaren 
Datei bleibt?

Viele Grüße
Nicolas

von Peter II (Gast)


Lesenswert?

lagere doch die Daten in eine Datei aus und laden sie zur laufzeit. Es 
ist doch sinnlos jedesmal eine neue Programm zu bauen, nur weil sich 
daten ändern.

von Walter T. (nicolas)


Lesenswert?

Peter II schrieb:
> lagere doch die Daten in eine Datei aus und laden sie zur laufzeit. Es
> ist doch sinnlos jedesmal eine neue Programm zu bauen, nur weil sich
> daten ändern.

Das ist genau das Gegenteil von dem, was ich will. Ich habe keinen 
Dateilademechanismus zur Verfügung (kein Dateisystem). Auch kein EEPROM 
oder sonstwie addressierbaren externen Speicher. Dafür bleiben die Daten 
dauerhaft konstant. Die Structures sind nur ein Vehikel, weil das 
Auslesen dann sehr komfortabel und übersichtlich geht.

von Peter II (Gast)


Lesenswert?

Nicolas S. schrieb:
> Das ist genau das Gegenteil von dem, was ich will. Ich habe keinen
> Dateilademechanismus zur Verfügung (kein Dateisystem).

du bist hier aber in bereich "PC-Programmierung" und dort gibes 
Dateisystem und ladefunktionen.

Man könnte als es obj-Datei direkt in den linker vorgang übernehmen, 
dann musst aber es aber selber noch in die Structur überführen.

von glückspilz (Gast)


Lesenswert?

Bei 10'000 Codezeilen sollte die Compilierzeit auf einer halbwegs 
modernen Maschine längst nicht so gross sein. Deine Variante ist also 
schon ok. Ich vermute mal, dass der Präprozessor oder der Compiler sich 
aus irgend einem Grund verrennt. Mehr kann ich dir aber beim besten 
Willen nicht helfen.

Peter II schrieb:
> lagere doch die Daten in eine Datei aus und laden sie zur laufzeit. Es
> ist doch sinnlos jedesmal eine neue Programm zu bauen, nur weil sich
> daten ändern.

Man kann auch umgekehrt argumentieren. Warum eine Laderoutine bauen, 
wenn sich die Daten sowieso nur selten ändern.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Das kann so nicht funktionieren:
1
int main() 
2
{
3
  Getier_t Getier = GETIER;
4
5
   ...
6
}

Das legt eine Struktur vom Typ Getier_t an.

Das #define "GETIER" aber ist eine Array-Initialisierung.

von Walter T. (nicolas)


Lesenswert?

Zum Testen habe ich in der Headerdatei die gleiche Zeile immer 
wiederholt, also quasi so:
1
#define GETIER {\
2
  {"Dirk","1/2 Haehnchen",true,1,familie,3.200000e-001},\
3
  {"Dirk","1/2 Haehnchen",true,1,familie,3.200000e-001},\
4
  {"Dirk","1/2 Haehnchen",true,1,familie,3.200000e-001},\
5
  {"Dirk","1/2 Haehnchen",true,1,familie,3.200000e-001},\
6
       ....
7
  {"Dirk","1/2 Haehnchen",true,1,familie,3.200000e-001},\
8
  {"Dirk","1/2 Haehnchen",true,1,familie,3.200000e-001},\
9
  {"Dirk","1/2 Haehnchen",true,1,familie,3.200000e-001},\
10
  {"Dirk","1/2 Haehnchen",true,1,familie,3.200000e-001},\
11
}
um auszuschließen, daß der Compiler sich an einer fehlerhafen Zeile 
verrennt. Außerdem besteht mein Testcode nur noch aus dem Deklarieren 
und Instanzieren dieses Structures, um Nebeneffekte auszuschließen.

Bei ca. 500 Zeilen geht das Ganze auch noch recht zügig vonstatten, bei 
mehr als 10000 Zeilen (Headerdatei über 1,2 MB) ist die Kompilierzeit 
immer noch bei mehr als 20 Minuten (danach abgebrochen). Der Rechner ist 
"schnell genug mit ausreichend Hauptspeicher (TM)". Also scheint die 
Methode nicht so toll geeignet zu sein.

Viele Grüße
Nicolas

P.S.: Im "Orignal" steht natürlich
1
const Getier_t Getier[] = GETIER;
ich habe mich nur beim Codekürzen vertippt.

von Mark B. (markbrandis)


Lesenswert?

Nicolas S. schrieb:
> Das ist genau das Gegenteil von dem, was ich will. Ich habe keinen
> Dateilademechanismus zur Verfügung (kein Dateisystem). Auch kein EEPROM
> oder sonstwie addressierbaren externen Speicher.

Ähm blöde Frage, aber was ist das für ein seltenes Zielsystem das genug 
Speicher hat für Deine Aktion, für das mit MS VC compiliert wird, aber 
das keinerlei Zugang zu einem Dateisystem haben soll? Nicht mal zu ner 
SD-Card? Das kann doch jeder poplige 4-Bit-Mikrocontroller, wenn man ihm 
eine dranlötet ;-)

von Sam P. (Gast)


Lesenswert?

Das sieht so aus, als ob sich der Compiler beim Optimieren einen 
abbricht. Vielleicht versucht er, konstante Werte direkt in den 
Assemblercode zu übernehmen, wenn er beim Compilen schon weiss, welches 
struct-Element benutzt wird.

Falls dem so ist, lagere die Variablendefinition in eine eigene Datei 
aus, die als separate Objektdatei gelinkt wird:

getier.h
1
extern const getier_t Getier[];

getier.c
1
const getier_t Getier[] = {
2
 ...
3
};

von Karl H. (kbuchegg)


Lesenswert?

Ich hab eher den Präprozessor in Verdacht, der sich mit der 
Makro-Textersetzung einen abbricht.

Probiers mal so

Werte.inc
1
 {"Helmut",  "Huhn",          false, 2, gattung, 1.000000e-001},
2
 {"Mark",    "Hund",          true,  4, art,     1.500000e+001},
3
 {"Margret", "Paarhufer",     false, 3, familie, 8.200000e+002},
4
 {"Dirk",    "1/2 Haehnchen", true,  1, familie, 3.200000e-001},

1
...
2
3
int main() {
4
   Getier_t Getier = {
5
#include "werte.inc"
6
   };
7
8
   ...
9
}

Wozu erst mal ein 2GB Makro anlegen, das kein Mensch braucht?

#include ist #include: Der Inhalt des Files wird an der Stelle 
reingezogen, an der der #include steht. Und erst dieses Endergebnis muss 
gültigen C Code ergeben. Kein Mensch schreibt vor, was in einem 
#includiertem File stehen muss.
Man kann auch so programmieren
1
#include "int.inc"
2
#include "main.inc"
3
#include "LeftParen.inc"
4
#include "RightParen.inc"
5
#include "LeftBrace.inc"
6
#include "RightBrace.inc"
und zusammen mit den entsprechenden zu includierenden Files

int.inc
1
int

main.inc
1
main

LeftParen.inc
1
(

....

ergibt sich nach den ganzen includes
1
int main(){}
welches ein gültiges C-Programm ist

von Yalu X. (yalu) (Moderator)


Lesenswert?

Der GCC braucht bei mir auf einem schon etwas betagteren Laptop für die
10000 Einträge 0,6 s. Die Headerdatei nach deinem Muster ist aber nicht
2 MB, sondern nur 580 kB groß. Trotzdem ist das ein riesiges Makro, was
dem MS-Compiler (bzw.Präprozessor) durchaus Schwierigkeiten machen
könnte. Deswegen würde ich auch den Weg von Karl Heinz vorschlagen.

von Walter T. (nicolas)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,
am Präprozessor liegt es wahrscheinlich nicht, da die Kompilierdauer für 
ein direktes Einsetzen im C-Quelltext ziemlich gleich ist.

Ich habe jetzt auf folgenden (lauffähigen) Quelltext gekürzt:
1
// MEX_loadgetier.c 
2
/* Test fuer das Kompilieren grosser Structures: Liegt hier der Flaschenhals? */ 
3
4
#include "mex.h"
5
#include "string.h"
6
#include "getier.h"
7
8
typedef char boolean;
9
typedef enum {reich,
10
              stamm,
11
              klasse,
12
              ordnung,
13
              familie,
14
              gattung,
15
              art } viecher_t;
16
17
typedef struct {
18
        const char*    name;       
19
        const char*    zeugs;      
20
        boolean        tot;
21
        unsigned int   beine;
22
        viecher_t      viech;
23
        double         masse;
24
     } Getier_t;
25
26
27
/* *********************       main       ****************************** */
28
void mexFunction(int nlhs, mxArray *plhs[],
29
        int nrhs, const mxArray *prhs[]) {
30
31
    const Getier_t Getier[] = GETIER;
32
    return;
33
}
die Includedatei "getier." wird automatisch erstellt und sieht so aus:
1
/* Configuration of struct Variables                        */
2
#define GETIER {\
3
     {"Helmut","Huhn",0,2,gattung,1.000000e-001},\
4
     {"Mark","Hund",1,4,art,1.500000e+001},\
5
     {"Margret","Paarhufer",0,3,familie,8.200000e+002},\
6
     {"Dirk","1/2 Haehnchen",1,1,familie,3.200000e-001},\
7
     {"Helmut","Huhn",0,2,gattung,1.000000e-001},\
8
     {"Mark","Hund",1,4,art,1.500000e+001},\
9
     {"Margret","Paarhufer",0,3,familie,8.200000e+002},\
10
     {"Dirk","1/2 Haehnchen",1,1,familie,3.200000e-001},\
11
     {"Helmut","Huhn",0,2,gattung,1.000000e-001},\
12
     {"Mark","Hund",1,4,art,1.500000e+001},\
13
       ...
14
     {"Margret","Paarhufer",0,3,familie,8.200000e+002},\
15
     {"Dirk","1/2 Haehnchen",1,1,familie,3.200000e-001},\
16
     {"Helmut","Huhn",0,2,gattung,1.000000e-001},\
17
     {"Mark","Hund",1,4,art,1.500000e+001}}
und das Ganze habe ich unter Matlab wie folgt kompilieren lassen:
1
%% Check handling of large structured arrays
2
% Design test for handling of large structured arrays
3
clear all
4
5
hName = 'getier.h';
6
inkrement = 1.5;
7
8
nRows = 10;
9
for testNo = 1:500
10
11
nRows = floor(nRows*inkrement);
12
13
% Structure content dummies
14
names = {'Helmut','Mark','Margret','Dirk'};
15
zeugs = {'Huhn','Hund','Paarhufer','1/2 Haehnchen'};
16
tot   = {false,true,false,true};
17
beine = {2,4,3,1};
18
viech = {'gattung','art','familie','familie'};
19
masse = {0.1,15,820,0.32};
20
21
% Generate header file
22
FID = fopen(hName,'w');
23
fprintf(FID,'\n\n/* Configuration of struct Variables                        */\n');
24
fprintf(FID,'#define GETIER {\\\n');
25
nVals = numel(names);
26
j = 1;
27
for i = 1:nRows
28
    str = '     {\"%s\",\"%s\",%i,%i,%s,%e},\\\n';
29
    fprintf(FID,str,names{j},zeugs{j},tot{j},beine{j},viech{j},masse{j});
30
    j = j+ 1;
31
    if j > nVals; j = 1; end
32
end
33
fseek(FID,-3,'cof');
34
fprintf(FID,'}\n');
35
fclose(FID);
36
37
% compile and measure time
38
tic
39
mex -v 'MEX_loadgetier01.c'
40
et = toc
41
42
   r(testNo) = nRows;
43
   t(testNo) = et;
44
   
45
   semilogy(r,t);
46
   grid on
47
   drawnow
48
49
end
und das Ergebnis ist die Kompilierzeit im Verhältnis zur Anzahl der 
Zeilen im includefile (siehe Bild).

Ich schaue mal, ob der Verlauf mit dem GCC reproduzierbar ist.

Viele Grüße
Nicolas

von Walter T. (nicolas)


Lesenswert?

Nachtrag: Der LCC kompiliert ab 500 Zeilen nicht mehr.

von Μαtthias W. (matthias) Benutzerseite


Angehängte Dateien:

Lesenswert?

Hi

hier mal ein Test unter Linux/x64 bis zu 50k Zeilen und gcc 4.6.3. Man 
beachte die unterschiedliche Skalierung der Y-Achse.

Lösung für das Ursprungsproblem:
Verwende den GCC :-)

Matthias

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Ist vielleicht sowas wie "precompiled Header" aktiviert?

von Rolf Magnus (Gast)


Lesenswert?

Warum wird das Objekt lokal angelgt? Sinnvoller wäre doch entweder 
global oder zumindest mal lokal, aber static. Sonst muß ja der gesamte 
Datenblock bei jedem Aufruf der Funktion erstmal auf den Stack kopiert 
werden.

von Walter T. (nicolas)


Angehängte Dateien:

Lesenswert?

Hallo zusammen.
Tatsache: Der GCC (hier Version 4.6.2) verschluckt sich nicht so leicht 
an größeren Headerdateien (siehe auch angehängtes Diagramm). Die 
entstandene DLL ist auch etwas kleiner als der ursprüngliche Datensatz.

Jetzt bleibt natürlich die Frage offen, wie dem MSVC Vernunft 
beizubringen ist - die Option, die Konstanten in einer fremdkompilierten 
DLL unterzubringen will ich erst gar nicht in Erwägung ziehen - auch 
genau aus dem Grund, den Rolf Magnus erwähnt: Die Konstanten werden nur 
von main() des Hauptprogramms und nur beim Start benötigt, deswegen soll 
das wenn möglich erst gar nicht im Speicher angelegt werden.

Vielen Dank für die interessante Diskussion
Nicolas

von Peter II (Gast)


Lesenswert?

Nicolas S. schrieb:
> deswegen soll
> das wenn möglich erst gar nicht im Speicher angelegt werden.

da main immer aktiv ist, wird es sowieso in den speicher geladen. Da ist 
kein unterschied zu einer globalen variable.

von Mark B. (markbrandis)


Lesenswert?

Nicolas S. schrieb:

> Jetzt bleibt natürlich die Frage offen, wie dem MSVC Vernunft
> beizubringen ist

Gibt es denn vernünftige Gründe dafür, gerade den MSVC zu verwenden, 
wenn man in C programmieren will?

Nimm doch einen Compiler, der auch C99 unterstützt.

von Walter T. (nicolas)


Lesenswert?

Mark Brandis schrieb:
>
> Gibt es denn vernünftige Gründe dafür, gerade den MSVC zu verwenden,
> wenn man in C programmieren will?
>

Wichtigster Grund ist für mich die Matlab-Unterstützung, der 
zweitwichtigste, daß ich mit dem Debugger so langsam klarkomme.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

1
Getier_t g1 = GETIER;
2
const Getier_t g2 = GETIER;
3
4
int main (void)
5
{
6
   Getier_t g3 = GETIER;
7
}
Welcher Code wird denn da für g1, g2, g3 erzeugt — vorausgesetzt, wie 
werden nicht wegoptimiert?

Für g1 gibt's 2 Möglichkeiten der Initialisierung:

1) Die Daten werden aus einem Literal ins RAM kopiert, z.B. im
   Standard CRT-Code.

2) Der Compiler erzeugt einen "künstlichen" Constructor, der zur
   init-Zeit aufgerufen wird, d.h. vor main.  Der Code in einem solchen
   Konstruktor funktioniert dann gemäß 4) oder 5)

Ditto für g2. Zusätzlich gibt's dafür noch die Möglichkeit

3) Ein Literal wird zur Load-Zeit vom Loader des OS' geladen,
   ebenso wie der Programmcode auch. Ein Kopieren zur Init-Zeit
   ist nicht nötig.

Für g3 gibt's folgende Möglichkeiten:

4) Der Kompiler erzeugt ein implizites Literal im read-only Bereich
   und kopiert diese Daten, indem er in Implizites memcpy erzeugt.

5) Der Compiler erzeugt einzelne Instruktionen; jede Instruktion
   initialisiert zB ein 8-, 16-, 32- oder 64-Bit Happen von g3.

Falls 5) verwendet wird, ist das natürlich sehr teuer, sowohl zur 
Compilerzeit als auch zu Laufzeit, denn der Compiler muss zig 
Instruktionen verwalten, compilieren, optimieren, ausgeben; evtl. 
Constant-Pools anlegen und verwalten, in den Pools suchen, etc. 
Ausserdem steigt die Codegröße linear mit der Größe des Objekts an.

GCC verwendet auch Mischformen zB 4) mit memset(0) und danach 5)

Bei GCC kann man all diese Strategiern beobachten; 5) allerdings nur 
dann, wenn das zu initialisierende Objekt klein ist.  Für Objekte, die 
größer als ein paar Worte sind, nimmt er dann 4)

Weiterer Grund für die Langsamkeit kann wie gesagt PCH sein.

GCC kennt den Schalter -Q, der Auskunft über den Resourcenverbrauch auf 
dem Host macht, ausgabe siehe unten.

Vielleicht gibt's sowas ja auch für den MSCV so daß man besser versteht, 
wo die Zeit draufgeht.
1
Execution times (seconds)
2
 phase setup             :   0.02 ( 5%) usr     506 kB (54%) ggc
3
 phase parsing           :   0.05 (13%) usr     191 kB (21%) ggc
4
 phase cgraph            :   0.31 (82%) usr     223 kB (24%) ggc
5
 phase generate          :   0.31 (82%) usr     223 kB (24%) ggc
6
 callgraph optimization  :   0.01 ( 3%) usr       3 kB ( 0%) ggc
7
 varpool construction    :   0.01 ( 3%) usr       0 kB ( 0%) ggc
8
 ipa SRA                 :   0.01 ( 3%) usr       2 kB ( 0%) ggc
9
 df scan insns           :   0.01 ( 3%) usr       0 kB ( 0%) ggc
10
 register scan           :   0.01 ( 3%) usr       0 kB ( 0%) ggc
11
 preprocessing           :   0.01 ( 3%) usr      19 kB ( 2%) ggc
12
 parser (global)         :   0.02 ( 5%) usr     144 kB (16%) ggc
13
 parser function body    :   0.02 ( 5%) usr      10 kB ( 1%) ggc
14
 tree gimplify           :   0.03 ( 8%) usr      10 kB ( 1%) ggc
15
 tree CFG cleanup        :   0.01 ( 3%) usr       0 kB ( 0%) ggc
16
 tree VRP                :   0.02 ( 5%) usr      12 kB ( 1%) ggc
17
 tree PTA                :   0.01 ( 3%) usr       0 kB ( 0%) ggc
18
 tree CCP                :   0.01 ( 3%) usr       1 kB ( 0%) ggc
19
 tree FRE                :   0.03 ( 8%) usr       5 kB ( 1%) ggc
20
 tree aggressive DCE     :   0.01 ( 3%) usr       6 kB ( 1%) ggc
21
 tree iv optimization    :   0.01 ( 3%) usr       5 kB ( 1%) ggc
22
 expand                  :   0.01 ( 3%) usr      24 kB ( 3%) ggc
23
 lower subreg            :   0.01 ( 3%) usr       4 kB ( 1%) ggc
24
 CSE 2                   :   0.01 ( 3%) usr       0 kB ( 0%) ggc
25
 combiner                :   0.01 ( 3%) usr       2 kB ( 0%) ggc
26
 integrated RA           :   0.02 ( 5%) usr      25 kB ( 3%) ggc
27
 reload                  :   0.01 ( 3%) usr       4 kB ( 1%) ggc
28
 hard reg cprop          :   0.01 ( 3%) usr       0 kB ( 0%) ggc
29
 uninit var analysis     :   0.02 ( 5%) usr       0 kB ( 0%) ggc
30
 rest of compilation     :   0.02 ( 5%) usr       4 kB ( 0%) ggc
31
 unaccounted todo        :   0.01 ( 3%) usr       0 kB ( 0%) ggc
32
 TOTAL                 :   0.38               929 kB

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Eventuell hilft dir dieser Ansatz weiter, hatte ich vor nicht 
allzulanger zeit mal probiert und hat eigentlich ganz gut funktioniert:
http://www.linuxjournal.com/content/embedding-file-executable-aka-hello-world-version-5967

Ziel da war ein Firmewareupdater welcher seine Firmware eingebettet 
mitbringt, sodass der Kunde nicht zwei Files laden muss.

von juna (Gast)


Lesenswert?

Nicolas S. schrieb:

> Wichtigster Grund ist für mich die Matlab-Unterstützung, der
> zweitwichtigste, daß ich mit dem Debugger so langsam klarkomme.

Mach nen Call beim Hersteller auf, ist ja schließlich kein 
Opensourcefrickel.

von (prx) A. K. (prx)


Lesenswert?

Was soll eigentlich der Spuk mit diesem Monster-Define? Warum nicht ein 
ganz normales statisches Array mit Initialisierung?

von Peter II (Gast)


Lesenswert?

So nun wollte ich es auch selber mal wissen.

Ich kann es bei mir nachvollziehen das es langsam ist. Aber wenn man die 
Variable globale macht, dann geht das ganze bei 100.000 einträgen in 
2sekunden.

Das ganze lokal und damit auf dem Stack zu machen, ist für diese menge 
an daten sowieso unpassend.
1
#include "test.h"
2
#include <stdio.h>
3
4
typedef enum {reich,
5
              stamm,
6
              klasse,
7
              ordnung,
8
              familie,
9
              gattung,
10
              art } viecher_t;
11
12
13
typedef struct {
14
        const char*    name;       
15
        const char*    zeugs;      
16
        bool           tot;
17
        unsigned int   beine;
18
        viecher_t      viech;
19
        double         masse;
20
     } Getier_t;
21
22
Getier_t Getier[] = GETIER;
23
24
int main() {
25
   //Getier_t Getier[] = GETIER;
26
  
27
   int count = sizeof(Getier)/sizeof(Getier_t);
28
   printf("Anzahl: %d\n", count);
29
   
30
   double ges_masse = 0;
31
   for( int i = 0; i < count; ++i ) {
32
      ges_masse += Getier[i].masse;
33
   }
34
35
   printf("gesamtmasse: %f\n", ges_masse);
36
   return 0;
37
}

von troll42 (Gast)


Lesenswert?

Darf man fragen was das werden soll? Klingt irgendwie spannend, so nach 
universeller Tierchendatenbank...

von Walter T. (nicolas)


Lesenswert?

Hallo zusammen,

A. K. schrieb:
> Was soll eigentlich der Spuk mit diesem Monster-Define? Warum nicht ein
> ganz normales statisches Array mit Initialisierung?

ist es das nicht? Sobald das define ausgeführt ist steht doch nichts 
anderes da ein statisches structure array. Die Auslagerung in ein define 
ist nur eine Komfortfunktion, da es etwas kompfortabler ist, eine 
.h-Datei zu erstellen mit define als in einem Quelltext nach einer 
Textstelle zu suchen und ersetzen. Das Ganze struct ist nur eine 
Komfortfunktion, um den Quelltext besser lesen zu können.

Peter II schrieb:
> Ich kann es bei mir nachvollziehen das es langsam ist. Aber wenn man die
> Variable globale macht, dann geht das ganze bei 100.000 einträgen in
> 2sekunden.

Danke für den Tipp, muß ich mal ausprobieren, sobald ich meinen Kaffee 
getrunken habe.

troll42 schrieb:
> Darf man fragen was das werden soll? Klingt irgendwie spannend, so nach
> universeller Tierchendatenbank...

Nein, das ist einfach ein hastig zusammengestricktes lauffähiges 
Minimalbeispiel, um die Problemstellung möglichst anschaulich darstellen 
zu können, sich nicht in Nebenschauplätzen des tatsächen Codes zu 
verlieren und "nebenbei" sicherzustellen, daß das Problem überhaupt an 
der Stelle ist, wo man es vermutet.

Viele Grüße
Nicolas

von Patrick (Gast)


Lesenswert?

Nicolas S. schrieb:
> A. K. schrieb:
>> Was soll eigentlich der Spuk mit diesem Monster-Define? Warum nicht ein
>> ganz normales statisches Array mit Initialisierung?
>
> ist es das nicht? Sobald das define ausgeführt ist steht doch nichts
> anderes da ein statisches structure array. Die Auslagerung in ein define
> ist nur eine Komfortfunktion, da es etwas kompfortabler ist, eine
> .h-Datei zu erstellen mit define als in einem Quelltext nach einer
> Textstelle zu suchen und ersetzen. Das Ganze struct ist nur eine
> Komfortfunktion, um den Quelltext besser lesen zu können.

Du hast Karl-Heinz' Beitrag 
Beitrag "Re: C - halbwegs große, konstante Structures" gelesen (und 
verstanden)?
Nach dem Lesen Deines ersten Postings war auch dies mein erster Gedanke: 
Solch riesige Textersetzungen macht "man" eigentlich nicht mit define's 
(bzw. ist es gut vorstellbar, dass hier der Hase im Pfeffer liegt, da 
die Textersetzung eigentlich nicht für derart große Strings ausgelegt 
ist).
Ist zumindest viel wahrscheinlicher, als die Schuld beim Compiler suchen 
zu wollen.

von Walter T. (nicolas)


Lesenswert?

Hallo Patrick,
ich habe den Beitrag gelesen, verstanden und ausprobiert. Und keinerlei 
meßbaren Unterschied in der Kompilierzeit in den Varianten mit und ohne 
Defines festgestellt. Siehe hier:

Nicolas S. schrieb:
> am Präprozessor liegt es wahrscheinlich nicht, da die Kompilierdauer für
> ein direktes Einsetzen im C-Quelltext ziemlich gleich ist.

Wenn bei einer derartigen Reihe kein Unterschied feststellbar ist, gehe 
ich davon aus, daß die diese Hypothese erst einmal verworfen werden 
sollte.

Viele Grüße
Nicolas

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

Auch wenn es nicht Hilft, solltest du das ohne Define machen, das 
verkompliziert doch die Sache nur... Hattest du meinen Link dir mal 
angeschaut? Wenn die Daten wirklich konstant sind könnte man da ja auch 
einmal ein OBJ draus kompilieren (dann dauerts halt ne Stunde...) und es 
später einfach nur dazulinken (lassen).

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Läubi .. schrieb:
> Auch wenn es nicht Hilft, solltest du das ohne Define machen,

Es geht doch nur um einen Testfall um das Problem nachzuvollziehen — 
das offenbar nix mit dem Define selbst zu tun hat.

Den Testfall aufzuhübschen macht den MSVC auch net schneller ;-)

von Christopher C. (Gast)


Lesenswert?

Warum nicht einfach Resource-Dateien benutzen?
Die werden einfach vom Linker mit in die EXE kopiert. Die kannst du dann 
ganz einfach auslesen, genau für sowas sind die doch da.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.