großes array dynamisch anlegen
-
...ich noch mal mit Beispiel konkret:
#include <stdio.h> #include <stdlib.h> #include <alloc.h> typedef unsigned long huge wert[40][40][40]; typedef unsigned long huge test[64000L]; wert *wertptr; test *testptr; int main(void) { unsigned long i; printf("size: %ld, %ld\n",sizeof(wert),sizeof(test)); wertptr = (wert*)farmalloc(sizeof(wert)); if(wertptr == NULL) printf("error\n"); else printf("ok\n"); testptr = wertptr; for(i=0;i<64000L;i++) (*testptr)[i] = 0L; (*wertptr)[0][0][2] = 123; for(i=0;i<64000L;i++) if((*testptr)[i] != 0L) printf("add %ld; wert %ld\n",i,(*testptr)[i]); getchar(); return(0); }
Ergebniss:
size: 256000, 256000
ok
add 2; wert 123
add 16386; wert 123
add 32770; wert 123
add 49154; wert 123stelle ich mich nun zu blöd an, dem array daten zu zuweisen?
Nebenbei: wenn ich in der farmalloc-Zeile "wert" durch "test" ersetze, kommt "error" also pointer NULL raus... grummel grummel...
Ich habe so ähnliche Sachen schon mit "typedef struct" gemacht, hat alles wunderbar geklappt, nur waren das keine großen array, die ich eben hier nicht in structuren reinkriege... und außerdem wars ein Motorola-Controller, der eben soviel Speicher ganz normal linear hintereinander hat wie physikalisch vorhanden... man geht das gut. Aber hier quäle ich mir ganz schön einen ab...
Ich bin kein C-Guru, beschäftige mich eher mit der Hardwareentwicklung, muß nur ab und zu auch bissel Weichware dazu machen. Der ganze Spaß läuft dann auf einem embedded-PC unter DOS...
-
Hallo Helmut, danke dir... ich hatte deinen Beitrag noch nicht gelesen bevor ich meine letzten Zeilen hier reindrückte... ich probiere das in paar Stunden aus, lege mich erstmal aufs Ohr. Gute Nacht und Danke noch mal.
-
macht's doch so:
struct wert_all_t { unsigned long wert_a[40][40]; unsigned long wert_b[128][128]; unsigned long wert_c; unsigned long wert_d; } *wert_all; // huge vor oder hinter den * ? ... wert_all = /*far*/malloc (sizeof(struct wert_all_t)); // speicher anlegen für alles wert_all->wert_a[10][10] = 0x1234; // so kannste was reinschreiben ...
finde ich viel einfacher. ausserdem braucht ihr nicht dieses dazuaddieren zum nächsten pointer usw...
-
Mit struct muss ich ja den vollen Speicher für ALLE arrays anlegen, das ist zuviel. Ich muss zur Laufzeit entscheiden was für ein array ich nutzen will und dann dynamisch den Speicher belegen. Zweites habe ich noch keinen Weg gefunden, mit struct mehr als 64kB anzulegen.
Also ich möchte das mal auf folgendendes Problem beschränken:
Dynamisches Anlegen und nutzen eines array:
unsigend long[40][40][40]Hallo Helmut, ich habe etwas rumgespielt mit deinem Vorschlag, aber das Problem bleibt vom Prinzip her das selbe.
Soweit so gut, das mit dem "wertptr_all" scheint auch gut zu funktionieren, doch mit dem Feld wert_a, gehts nicht, sobald ich über die magischen 64KB komme spiegelt der wieder in die anderen Adressen.
Programm:#include <stdio.h> #include <stdlib.h> #include <alloc.h> typedef unsigned long huge* wert_all; // wert_all[0x12000L]; typedef unsigned long huge (*wert_a)[40][40]; // wert_a[40][40][40]; typedef unsigned long huge (*wert_b)[128][128]; // wert_b[4][128][128]; typedef unsigned long huge* wert_c; // wert_c[4096]; typedef unsigned long huge* wert_d; // wert_d[4096]; wert_all wertptr_all; wert_a wertptr_a; wert_b wertptr_b; wert_c wertptr_c; wert_d wertptr_d; int main() { unsigned long i; wertptr_all = (wert_all)farmalloc(0x12000L*sizeof(unsigned long)); if(wertptr_all == NULL) printf("error\n"); else printf("ok\n"); // ich weise allen Feldern zunächst die selbe Startadresse zu wertptr_d = (wert_d)wertptr_all; wertptr_c = (wert_c)wertptr_all; //+ 0x1000); wertptr_b = (wert_b)wertptr_all; //+ 0x2000); wertptr_a = (wert_a)wertptr_all; //+ 0x2000); for(i=0;i<0x12000L;i++) wertptr_all[i] = 0L; // alles 0 wertptr_a[0][0][0] = 123; wertptr_a[0][0][1] = 124; wertptr_a[1][0][0] = 125; wertptr_a[2][0][0] = 126; wertptr_a[4][0][0] = 127; wertptr_a[8][0][0] = 128; wertptr_a[10][9][0] = 129; wertptr_a[10][10][0] = 130; wertptr_all[0x11fff] = 99; for(i=0;i<0x12000L;i++) if(wertptr_all[i] != 0L) printf("add %ld; wert %ld\n",i,wertptr_all[i]); getchar(); return 0; }
Das führt zu folgender Ausgabe:
----------------------------
ok
add 0; wert 123
add 1; wert 124
add 16; wert 130
add 1600; wert 125
add 3200; wert 126
add 6400; wert 127
add 12800; wert 128
add 16360; wert 129
add 73727; wert 99
----------------------------
beachte wert 130 wo der steht!Rüste ich das Programm ab und nutze nur das Feld wert_a, weise diesem auch nur Speicher zu usw. ist das Ergebins das gleiche, sobald ich array-mäßig über 64kB komme, steht mist im Feld. Einstellungsmäßig habe ich schon so alles mögliche probiert.. huge-model etc. ; immer das selbe Problem.
-
KBlaubaer schrieb:
Mit struct muss ich ja den vollen Speicher für ALLE arrays anlegen, das ist zuviel.
dann nimm statt struct 'union'. das belegt nur speicher für das grösste element (allerdings beginnen dann alle struct-menbers an der gleichen adresse)...
KBlaubaer schrieb:
Zweites habe ich noch keinen Weg gefunden, mit struct mehr als 64kB anzulegen.
das speicher-anlegen macht doch dein 'farmalloc'
-
Hallo!
ok
add 0; wert 123
add 1; wert 124
add 1600; wert 125
add 3200; wert 126
add 6400; wert 127
add 12800; wert 128
add 16360; wert 129
add 16400; wert 130
add 73727; wert 99 das ist die Ausgabe unter Windows XP, Compiler VC 8.0,bei Dir steht noch add 16; wert 130 - Dein Compiler packt es scheinbar nicht!
Bei Dir auch >> 73727; wert 99 sehr gut! - der halbe Sieg!
Problem ist, ich hab auf keinem PC mehr DOS zu laufen geschweige habe ich Deinen Borland-C Compiler.
Kann also praktisch nichts, was Dein Programm angeht (unter Speichermodell Huge) testen.
Damals, Anfang/Mitte der 90er Jahre hab ich unter DOS ausschliesslich in Assembler programmiert.
Wenn Dein Compiler es nicht bringt, wenn 64k überschritten werden, lassen wirs den Präprozessor machen.
Im Speicher wird alles eindimensional abgelegt, auch das was wir dreidimensional sehen wollen.
Was sich nun wieder ändert ist die Schreibweise für mehrdimensionale Arrays, ich setze dafür nun Makros ein.
Dein Compiler bekommt nur noch eindimesionales zu sehen, der Präprozessor übernimmt die Berechnung der Dimensionen.
Ich ändere Dein Programm mal in diesem Sinne und hoffe es klappt nun auch bei Dir.#include <stdlib.h> //Auch hier wird die erste Dimension weglassen! //D3(wert_a[40][40][40];) E3(wert_b[4][128][128];) #define D3_2 40 #define D3_3 40 #define D3(a, b, c) ((a*D3_2*D3_3)+(b*D3_3)+c) #define E3_2 128 #define E3_3 128 #define E3(a, b, c) ((a*E3_2*E3_3)+(b*E3_3)+c) // für 2D-Arrays #define D2_2 5 #define D2(a, b) a*D2_2+b typedef unsigned long* wert_all; // wert_all[0x12000L]; typedef unsigned long* wert_a; // wert_a[40][40][40]; typedef unsigned long* wert_b; // wert_b[4][128][128]; typedef unsigned long* wert_c; // wert_c[4096]; typedef unsigned long* wert_d; // wert_d[4096]; wert_all wertptr_all; wert_a wertptr_a; wert_b wertptr_b; wert_c wertptr_c; wert_d wertptr_d; int main() { unsigned long i; wertptr_all = (wert_all)malloc(0x12000L*sizeof(unsigned long)); if (wertptr_all == NULL) printf("error\n"); else printf("ok\n"); wertptr_d = (wert_d)wertptr_all; wertptr_c = (wert_c)(wertptr_all+0x1000); wertptr_b = (wert_b)(wertptr_all+0x2000); wertptr_a = (wert_a)(wertptr_all+0x2000); for (i=0; i < 0x12000L; i++) wertptr_all[i] = 0L; // alles 0 wertptr_a[D3(0, 0, 0)] = 123; wertptr_a[D3(0, 0, 1)] = 124; wertptr_a[D3(1, 0, 0)] = 125; wertptr_a[D3(2, 0, 0)] = 126; wertptr_a[D3(4, 0, 0)] = 127; wertptr_a[D3(8, 0, 0)] = 128; wertptr_a[D3(10,9, 0)] = 129; wertptr_a[D3(10,10,0)] = 130; wertptr_all[0x11fff] = 99; for (i=0;i<0x12000L;i++) if (wertptr_all[i] != 0L) printf("add %ld; wert %ld\n",i,wertptr_all[i]); getchar(); return 0; }
Ausgabe:
ok
add 8192; wert 123
add 8193; wert 124
add 9792; wert 125
add 11392; wert 126
add 14592; wert 127
add 20992; wert 128
add 24552; wert 129
add 24592; wert 130
add 73727; wert 99mfg
-
Danke Helmut, du bist ja wie 'ne Mutter
Aber ich getrau mir das gar nicht zu sagen... klappt nicht, nun spiegelt der in alle 64kB-Blöcke die Werte von dem array. Das Problem ist sicher das dreidimensionale Feld... mit einer dimension scheint das zu klappen... hmmm.
Sag mal, erzeugt dein compiler auch nen 16-Bit code für DOS? Es wäre einfach mal interessant zu testen, ob die exe dann bei mir läuft?
Ich wollte eigentlich nicht so 'nen Aufwand betreiben und 'ne neue Umgebung einsetzen... naja mal sehen...
Einen Versuch vielleicht noch. Mir egal, soll das Programm doch die ca 260kB größer werden... ich erzeuge statisch ein großes Feld und weise dann pointer dort rein... geht das?
gugge:#include <stdio.h> #include <stdlib.h> unsigned long huge wert_all[0x12000L]; unsigned long huge ***wert_vb4; // 40 40 40 int main(void) { unsigned long i; wert_vb4 = wert_all; // wie mache ich das richtig? printf("los gehts\n"); for(i=0;i<0x12000L;i++) wert_all[i] = 0x0L; wert_vb4[0][0][0] = 122; wert_vb4[8][0][0] = 123; wert_vb4[32][0][0] = 124; for(i=0;i<0x12000L;i++) if(wert_all[i] != 0L) printf("add %ld; wert %ld\n",i,wert_all[i]); getchar(); return(0); }
so kommt noch nix an, ich vermute die Zuweisung der Adresse von "wert_vb4" stimmt nicht.
-
so
#include <stdio.h> #include <stdlib.h> unsigned long huge wert_all[0x12000L]; typedef unsigned long huge (*wert_vb4)[40][40]; // 40 40 40 int main(void) { unsigned long i; wert_vb4 b4 = (wert_vb4 )wert_all; // wie mache ich das richtig? printf("los gehts\n"); for(i=0;i<0x12000L;i++) wert_all[i] = 0x0L; b4[0][0][0] = 122; b4[8][0][0] = 123; b4[32][0][0] = 124; for(i=0;i<0x12000L;i++) if(wert_all[i] != 0L) printf("add %ld; wert %ld\n",i,wert_all[i]); getchar(); return(0); }
-
Ihr seid alle wie MAMAs
Danke.
Wie nähern uns der Lösung ungemein.
Erstmal Entschuldigung Helmut, ich hab das heute früh nur schnell probiert, war den Tag bis jetzt im Auto unterwegs und habe nachgedacht das ich mich nur zu blöd angestellt habe, also vergessen meine "huge" und "far" wieder einzubauen... sorry das Thema nervt mich nun schon ganz schön...
Das mit dem #define ist schon prima Idee, so sollte es gehen.
Den letzten Vorschlag probiere ich auch gleich aus, sieht gut aus...
Ich heute noch mal Bescheid über meine Versuche... aber nun sollte es wohl klappen
-
Na einen zum lachen hab ich noch... wenn es nicht so traurig wäre...
Also Helmut, ist ja klar das muss funktionieren, weil es ja mit einer Dimension und dem Feld klappt, ganz klar. Nee... jetzt war bei 128kB Schuß mit lustig, wie, was, geht nicht, gibts nicht, doch
Lösung:
bei #define nimmt der standardmäßig signed int und die gehen nur bis 32xxx... danach wars negativ, grins mich weg, also erst die Zeilen:
#define D3_2 40L
#define D3_3 40L
#define D3(a, b, c) ((a*D3_2*D3_3)+(b*D3_3)+c)
brachten die Lösung.
Oh Mann, schwere Geburt, ich hab mir das nicht freiwillig ausgesucht mit dem DOS... nur mal so zur Info
Das andere von >>EXDOS<< mit dem pointer funktionierte, aber natürlich wieder die Beschränkung auf 64kB...
Also Leute DANKE noch mal.