[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: integer groesser 2^31 in C




On Mon, 30 Jun 2003, Erik Thiele wrote:

> On Sun, 29 Jun 2003 17:11:42 +0200 (CEST)
> Achim Fritz <fritzam@mathematik.uni-stuttgart.de> 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:
> > fritzam@vwin:~/ugspeicher/test-proc> echo "2^31"|bc
> > 2147483648
> > fritzam@vwin:~/ugspeicher/test-proc> echo "2^32"|bc
> > 4294967296
> > fritzam@vwin:~/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
>



Reply to: