On Mon, 30 Jun 2003, Erik Thiele wrote:
> On Sun, 29 Jun 2003 17:11:42 +0200 (CEST) > Achim Fritz <[EMAIL PROTECTED]> wrote: > > > Hi, > > > > fuer ein Finite-Element-Programm in C, muesste ich unbedingt mehr als 2Gb > > Speicher allokieren. Der Rechner hat 2Gb Speicher und 2Gb Swap. > > du kannst nicht mehr als 4GB Speicher allokieren da der pointer datentyp 32Bit ist > (auf 32Bit Maschinen). > (void*) zum beispiel. > > es ist auch nicht moeglich, mehrere 4GB bereiche zu allokieren, da in C der gesamte > allokierte Speicherbereich über Pointer zugänglich sein muss. > > gleichwohl mag linux insgesamt mehr als 4GB RAM verwalten, so dass einzelne Prozesse > (nicht Threads!) jeweils die 4GB erreichen können. > > > Ich habe erst gedacht, es liegt am Kernel (CONFIG_HIGHMEM ist gesetzt), > > habe jetzt aber festgestellt, dass es nicht moeglich ist in C eine Integer > > zu deklarieren, die groesser als 2^31 ist. > > zunächst einmal > > #include <sys/types.h> > > und dann: > > u_int32_t > int32_t > > usw. verwenden statt int und long long. sonst ist dein code nicht portabel. > datentypen wie int und long etc. sind per definition eine sünde und jede > programmiersprache die sie besitzt ist murx. > > ausnahme zum beispiel das gute alte lisp, wo der datentyp int seinem > namen gerecht wird und _beliebig_ grosse zahlen aufnehmen kann. > > doch zurueck zum thema, du musst also zunaechst einmal klarstellen, welche > datentypen du verwenden moechtest. jetzt zu deinem problem mit der zuweisung: > > u_int32_t x = 4294967295; > > --> mist.c:5: warning: decimal integer constant is so large that it is unsigned > > das problem ist hier, dass der compiler die symbole zunaechst einmal einzeln parst. > er sieht eine ziffernfolge: "234879" und macht daraus ein Integer Symbol, > also eine Konstante vom Datentyp "int". Je nach compiler und platform ergeben > sich daraus unterschiedliche limitierungen. bei einer 32bit maschine ist zum beispiel > 2147483647 der groesstmoegliche wert. bei einer 16bit maschine ist es halt 32767. > dass du das hier in eine variable zuweisst, die den wert aufnehmen kann ist zu dem > zeitpunkt unbekannt. der compiler sieht einfach diese zahl und will sie einlesen. > ergo musst du ihm sagen, dass es sich hierbei um eine grosse zahl handelt: > > u_int32_t x = 4294967295u; > > siehst du das u am ende der zahl? das steht fuer unsigned. er soll also hier keinen > int lesen, sondern einen unsigned int. dann klappts auch, weil der wert da reinpasst. > das problem geht aber noch weiter: > > u_int64_t y = 2999999999999u; > > mist.c:6: integer constant out of range > > das ding passt eben nicht in einen unsigned int. zumindest nicht auf einer > 32bit maschine! also musst du machen: > > u_int64_t y = 2999999999999ll; > > ll steht fuer long long. ja richtig, der grosse mist mit unportablen datentyp- > groessenangaben setzt sich hier leider fort und alles ist wieder unportabel. > wenigstens kriegst du compiler errors wenn du das suffix hinten nicht richtig gemacht > hast. > > wenn du jetzt an das limit vorzeichenloser 64 bit zahlen faehrst: > > u_int64_t oo=18446744073709551615ll; > > --> mist.c:7: warning: decimal integer constant is so large that it is unsigned > > musst du eben das u wieder dazu machen: > > u_int64_t oo=18446744073709551615ull; > > > das gesamte integer handling ist kacke in C und in den meisten anderen sprachen > leider auch. > > > > Hab schon mehrere Compiler ausprobiert (unter anderem auch Borland auf > > Windows) und in den manpage von gcc nach optionen gesucht. > > (2.4.21 hab ich auch schon getestet) > > es ist unabhaengig vom compiler. C ist so definiert. > > > Der Kernel hat auch keine Probleme mit grossen Zahlen: > > [EMAIL PROTECTED]:~/ugspeicher/test-proc> echo "2^31"|bc > > 2147483648 > > [EMAIL PROTECTED]:~/ugspeicher/test-proc> echo "2^32"|bc > > 4294967296 > > [EMAIL PROTECTED]:~/ugspeicher/test-proc> echo "2^100"|bc > > 1267650600228229401496703205376 > > das hat nichts mit dem kernel zu tun. bc ist ein programm, > und das kann es halt. > > > Hat jemand ne Ahnung, oder ne Idee? > > jep. probier mal: > > #include <stdio.h> > #include <stdlib.h> > > int main() > { > void *buf = malloc ( (size_t) (3000000000u) ); // genau 3 GB > if (buf==0) printf("oh no\n"); else printf("yeah\n"); > return 0; > }; > Hallo Erik, erstmal danke fuer Deine ausfuehrliche Beschreibung. leider funktioniert es nicht: oh no (mit 2000000000u gehts) Noch ne Idee? Gruss Achim > > du musst denke ich deinen algorithmus gruendlich ueberdenken und mittels > zwischenspeichern auf festplatte > den speicherbedarf __drastisch__ reduzieren. > > das daemliche unix 32-bit design in verbindung mit der diesbezueglich ziemlich > daemlichen Sprache C > erbringt uns derzeit das naechste grosse problem der art wie sie schon so oft da > war. man denke nur > an das alte MS-DOS mit expanded memory, extended memory, hi memory area, 64kb offset > size und 16bit pointer > sowie dem pseudo 32bit pseudo seg+offs pointermist. > > erste auslaeufer sind erkennbar mit den sogenannten large-files. sie koennen > groesser als 2GB sein. > man muss seine programme entsprechend umprogrammieren, damit sie mit solchen dateien > umgehen koennen. > > der naechste mist ist schon vorprogrammiert. bei 128bit maschinen gibt es dann > large-large files. > besonders sinnvolle namensgebung uebrigens. > > MfG > Erik > > -- > Erik Thiele > -- Haeufig gestellte Fragen und Antworten (FAQ): http://www.de.debian.org/debian-user-german-FAQ/ Zum AUSTRAGEN schicken Sie eine Mail an [EMAIL PROTECTED] mit dem Subject "unsubscribe". Probleme? Mail an [EMAIL PROTECTED] (engl)