Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Welcher Datentyp für große Zahlen?

1 view
Skip to first unread message

Dominik Schmidt

unread,
Nov 24, 2009, 11:32:41 AM11/24/09
to
Hallo,

ich bin neu in C/C++ (ich beschr�nke mich derzeit auf C++).

Ich bin grunds�tzlich am �berlegen, wie ich Variablen deklarieren sollte,
die numerische Werte enthalten.
Wenn ich mir irgendwelche Beispielcodes durchlese, werden solche Variablen
immer als Integer (int var;) deklariert.
Nun Frage ich mich, ob es nicht grob fahrl�ssig ist, so vorzugehen.

In einem Beispiel habe ich gelesen, wie die Gr��e einer Datei ermittelt
wird, das Ergebnis wird in einer Integer-Variable gespeichert. Das
funktioniert nat�rlich hervorragend bei kleinen Dateien. Aber es gibt eine
Grenze (ich glaube etwa 2 GB?).
Meine Vermutung hat sich best�tigt, als ich die Gr��e einer 7 GB gro�en
Datei ermitteln wollte: Es kam ein unsinniger (negativer) Wert heraus.

Was w�re also die sauberste und beste Vorgehensweise, um in solchen F�llen
(wenn man also Zahlen unbekannter Gr��e bekommt) den gr��ten Datentyp
w�hlt, der existiert?

Ich habe in meinem Fall einfach als long long deklariert (soll angeblich
bis 9223372036854775807 gehen?), dann hat die Sache funktioniert, hier noch
der Code:

long long GetFileSize(string FilePath)
{
long long Out1 = -1;
ifstream file1;
file1.open (FilePath.c_str());
if (file1.is_open())
{
file1.seekg(0, ios::end);
Out1 = file1.tellg();
}
file1.close();

return Out1;
}

Georg Bauhaus

unread,
Nov 24, 2009, 12:39:22 PM11/24/09
to
Dominik Schmidt schrieb:

> In einem Beispiel habe ich gelesen, wie die Gr��e einer Datei ermittelt
> wird, das Ergebnis wird in einer Integer-Variable gespeichert.

Long, vermutlich?

> Was w�re also die sauberste und beste Vorgehensweise, um in solchen F�llen
> (wenn man also Zahlen unbekannter Gr��e bekommt) den gr��ten Datentyp
> w�hlt, der existiert?

Sauber ist nur eines, n�mlich genau diejenigen Datentypen zu
w�hlen, die in solchen F�llen vorgesehen sind.

(Die Antworten in d.c.l.c werden vermutlich f�r C gegeben,
f�r C++ (eine andere Sprache, trotz historischer
�berlappungen, besonders auch bei den I/O-Klassen vs
den C-Funktionen) wird von woanders Hilfe wahrscheinlicher sein.)

Wenn du die Frage nach Typen f�r Ganzzahl-I/O oder -Nutzung so
allgemein formulierst: Wie soll, ganz technisch, eine zu gro�e Zahl
in eine Variable eines zu kleinen Datentyps gespeichert
werden k�nnen? Geht nicht wirklich.

Wenn die Frage spezieller auf Dateioperationen zielt:
F�r eine gegebene C-Implementierung kann der Datentyp int
2G - 1 nichnegative Werte umfassen. Das muss aber f�r
Dateioperationen nichts hei�en: Denn die C-Funktion
aus der Standard-B�cherei von C wie fseek(3) oder fsetpos(3)
sehen jeweils andere Datentypen f�r Gr��en- bzw. Positionsangaben
vor: zum Beispiel long und fpos_t. Aber fpos_t muss nicht mal
unter der Haube ein Ganzzahltyp sein:

"Although fpos_t has traditionally been an integral type,
applications cannot assume that it is; in particular,
they must not perform arithmetic on objects of this type."
(BSD)

fpos_t hat also nach Definition gar nichts mit int zu tun.
Auch nicht mit long.

"On some non-UNIX systems an fpos_t object may be a complex object
and these routines may be the only way to portably reposition a
text stream." (GNU/Linux)

Demnach ist es nicht gut, wenn �berhaupt m�glich, ein Objekt
wie eine(n) Datei(zeiger) mit Werten zu manipulieren, deren Typ nicht
daf�r vorgesehen ist: int ist nicht f�r Dateioperationen wie
ftell(3) vorgesehen, sondern long; fgetpos(3) bekommt
einen fpos_t.

Wirf das mal deinem compiler zu, vielleicht sagt das Ding was
zu den verwendeten Typen, vielleicht aber auch nicht:

int vorsicht;

vorsicht = ftell(...);

Thomas Koller

unread,
Nov 24, 2009, 1:46:11 PM11/24/09
to
Dominik Schmidt <dominik...@gmx.net> wrote:
> ich bin neu in C/C++ (ich beschr�nke mich derzeit auf C++).

Warum fragst du dann hier?
Hier geht's um C nicht um C++, meine Antworten daher auch f�r C
und nicht f�r C++.

> Ich bin grunds�tzlich am �berlegen, wie ich Variablen deklarieren sollte,
> die numerische Werte enthalten.
> Wenn ich mir irgendwelche Beispielcodes durchlese, werden solche Variablen
> immer als Integer (int var;) deklariert.
> Nun Frage ich mich, ob es nicht grob fahrl�ssig ist, so vorzugehen.

Nein, �berhaupt nicht, man muss nur �ber die Einschr�nkungen
Bescheid wissen. z.b. dass bei int nur ein Wertebereich von
-32767 bis +32767 garantiert ist. Der Wertebereich kann auf manchen
Systemen auch gr��er sein, aber das sind halt die Mindestwerte.

> In einem Beispiel habe ich gelesen, wie die Gr��e einer Datei ermittelt
> wird, das Ergebnis wird in einer Integer-Variable gespeichert. Das
> funktioniert nat�rlich hervorragend bei kleinen Dateien. Aber es gibt eine
> Grenze (ich glaube etwa 2 GB?).

Nein, die liegt schon bei 32767 Byte. s.o.

> Meine Vermutung hat sich best�tigt, als ich die Gr��e einer 7 GB gro�en
> Datei ermitteln wollte: Es kam ein unsinniger (negativer) Wert heraus.

Die Dateigr��e portabel auszulesen ist ohnehin keine triviale Sache,
insofern ist das kein gutes Beispiel. Geht ja schon bei der Frage los
was die Dateigr��e ist. Die Zahl der Bytes die man im Bin�rmodus
lesen kann? Die Zahl der Bytes die man im Textmodus lesen kann?
Die Zahl der Bytes welche die Datei am Speichermedium verbraucht? ...

Du kannst dir ja mal die C-Faq zu dem Thema durchlesen.

> Was w�re also die sauberste und beste Vorgehensweise, um in solchen F�llen
> (wenn man also Zahlen unbekannter Gr��e bekommt) den gr��ten Datentyp
> w�hlt, der existiert?

Der gr��te Datentyp w�re in C intmax_t.

> Ich habe in meinem Fall einfach als long long deklariert (soll angeblich
> bis 9223372036854775807 gehen?),

Ja, das ist der garantierte Mindestbereich. Kann aber auch mehr sein.

Mit unsigned long long kommst sogar garantiert bis 18446744073709551615,
das ist dann auch das gr��te dass du garantiert bekommst.

> dann hat die Sache funktioniert, hier noch
> der Code:
>
> long long GetFileSize(string FilePath)
> {
> long long Out1 = -1;
> ifstream file1;
> file1.open (FilePath.c_str());
> if (file1.is_open())
> {
> file1.seekg(0, ios::end);
> Out1 = file1.tellg();
> }
> file1.close();
>
> return Out1;
> }

Auch wenns C++ ist, warum wechselst du eigentlich den Typ, und nimmst
nicht einfach den Typ den dir tellg liefert? (In dem Fall streampos).

Wenn dir beispielsweise in C die Funktion ftell nur ein long int
zur�ckliefert, hilft es dir genau nix, wenn du das einem long long int
zuweist, dadurch bekommst auch keine Filegr��en jenseits LONG_MAX.

Tom

Rainer Weikusat

unread,
Nov 24, 2009, 1:50:44 PM11/24/09
to
Dominik Schmidt <dominik...@gmx.net> writes:

[...]

> In einem Beispiel habe ich gelesen, wie die Gr��e einer Datei ermittelt
> wird, das Ergebnis wird in einer Integer-Variable gespeichert. Das
> funktioniert nat�rlich hervorragend bei kleinen Dateien. Aber es gibt eine
> Grenze (ich glaube etwa 2 GB?).
> Meine Vermutung hat sich best�tigt, als ich die Gr��e einer 7 GB gro�en
> Datei ermitteln wollte: Es kam ein unsinniger (negativer) Wert
> heraus.

'Groesse einer Datei' ist kein durch die C-Norm definierter Begriff
und die Antwort auf diese Frage ist plattformspezifisch. Fuer UNIX(*)
lautet sie off_t.

[...]

> Was w�re also die sauberste und beste Vorgehensweise, um in solchen F�llen
> (wenn man also Zahlen unbekannter Gr��e bekommt) den gr��ten Datentyp
> w�hlt, der existiert?

'Zahlen unbekannter Groesse' kann mit elementaren Datentypen der
Sprache C nicht handhaben, da diese alle einen maximalen Wertbereich
haben.

Stefan Reuther

unread,
Nov 24, 2009, 2:18:06 PM11/24/09
to
Dominik Schmidt wrote:
> In einem Beispiel habe ich gelesen, wie die Gr锟斤拷e einer Datei ermittelt
> wird, das Ergebnis wird in einer Integer-Variable gespeichert. Das
> funktioniert nat锟絩lich hervorragend bei kleinen Dateien. Aber es gibt eine
> Grenze (ich glaube etwa 2 GB?).

Sei froh, unter DOS w锟絩e die Grenze bei 32k :-)

> Meine Vermutung hat sich best锟絫igt, als ich die Gr锟斤拷e einer 7 GB gro锟絜n

> Datei ermitteln wollte: Es kam ein unsinniger (negativer) Wert heraus.
>

> Was w锟絩e also die sauberste und beste Vorgehensweise, um in solchen F锟絣len
> (wenn man also Zahlen unbekannter Gr锟斤拷e bekommt) den gr锟斤拷ten Datentyp
> w锟絟lt, der existiert?

Man w锟絟lt die zum API passenden Typen. C's <stdio.h> hat zum einen
ftell/fseek, die als Parameter 'long' nehmen. Damit kommst du auf heute
锟絙lichen Systemen bis 2 GByte. Klar, ist 'ne Einschr锟絥kung, aber es ist
nicht wirklich sinnvoll, als Nutzer dieser Funktionen dann einen anderen
Typen zu nutzen.

Au锟絜rdem gibt es fgetpos/fsetpos mit 'fpos_t', mit denen du dir zwar
Positionen in beliebig gro锟絜n Dateien merken kannst, wo du aber sonst
portabel nicht allzuviel mit machen kannst.

> Ich habe in meinem Fall einfach als long long deklariert (soll angeblich
> bis 9223372036854775807 gehen?),

'long long' geht mindestens bis 2**63-1.

> dann hat die Sache funktioniert, hier noch der Code:
>
> long long GetFileSize(string FilePath)
> {
> long long Out1 = -1;
> ifstream file1;
> file1.open (FilePath.c_str());
> if (file1.is_open())
> {
> file1.seekg(0, ios::end);
> Out1 = file1.tellg();

Abgesehen davon, dass C++ nach nebenan geh锟絩t: in C++ lautet der Typ f锟絩
die Stream-Position 'istream::pos_type'. Ob und in welchen ganzzahligen
Typ man den portabel wandeln darf, ist im Sprachstandard so gut
versteckt, dass ich es jetzt nicht finde.


Stefan

Dominik Schmidt

unread,
Nov 24, 2009, 2:40:05 PM11/24/09
to
On Tue, 24 Nov 2009 18:39:22 +0100, Georg Bauhaus wrote:

> Dominik Schmidt schrieb:
>
>> In einem Beispiel habe ich gelesen, wie die Gr��e einer Datei ermittelt
>> wird, das Ergebnis wird in einer Integer-Variable gespeichert.
>
> Long, vermutlich?

Ja, ich meinte Long.

> Sauber ist nur eines, n�mlich genau diejenigen Datentypen zu
> w�hlen, die in solchen F�llen vorgesehen sind.
>
> (Die Antworten in d.c.l.c werden vermutlich f�r C gegeben,
> f�r C++ (eine andere Sprache, trotz historischer
> �berlappungen, besonders auch bei den I/O-Klassen vs
> den C-Funktionen) wird von woanders Hilfe wahrscheinlicher sein.)

Also auf Deutsch: Ich bin in der falschen NG, richtig?
Vermutlich w�re de.comp.lang.iso-c++ besser, nehme ich an?

> Wenn du die Frage nach Typen f�r Ganzzahl-I/O oder -Nutzung so
> allgemein formulierst: Wie soll, ganz technisch, eine zu gro�e Zahl
> in eine Variable eines zu kleinen Datentyps gespeichert
> werden k�nnen? Geht nicht wirklich.

Nein, sicher, alles hat seine Grenzen.
Aber Dateien k�nnen eben gr��er als 2 GB sein. In einem solchen Fall kann
ich doch die Dateigr��e nicht in einer Long-Variable speichern (hat ja auch
nicht funktioniert)?
Float ist auch ungeeignet, da eine exakte (positive) Ganzzahl herauskommen
soll.
Und wenn die maximale Gr��e einer Long Long Variable tats�chlich bei
9223372036854775807 liegt (8 Exabyte?), w�re dieser Datentyp doch eher
geeignet, da ich davon ausgehe, dass mein Programm niemals mit einer solch
gro�en Datei umgehen muss (sondern immer mit kleineren)?

error: invalid conversion from `void*' to `FILE*'|

Passt das denn in meine Funktion?

Bitte hab Verst�ndnis, bin eben noch ein wenig neu (vorher fast nur VB6)...

Thomas Koller

unread,
Nov 24, 2009, 2:52:28 PM11/24/09
to
Dominik Schmidt <dominik...@gmx.net> wrote:
>> (Die Antworten in d.c.l.c werden vermutlich f�r C gegeben,
>> f�r C++ (eine andere Sprache, trotz historischer
>> �berlappungen, besonders auch bei den I/O-Klassen vs
>> den C-Funktionen) wird von woanders Hilfe wahrscheinlicher sein.)
>
> Also auf Deutsch: Ich bin in der falschen NG, richtig?

Ja

> Vermutlich w�re de.comp.lang.iso-c++ besser, nehme ich an?

Nochmal ja.

>> Wenn du die Frage nach Typen f�r Ganzzahl-I/O oder -Nutzung so
>> allgemein formulierst: Wie soll, ganz technisch, eine zu gro�e Zahl
>> in eine Variable eines zu kleinen Datentyps gespeichert
>> werden k�nnen? Geht nicht wirklich.
>
> Nein, sicher, alles hat seine Grenzen.
> Aber Dateien k�nnen eben gr��er als 2 GB sein. In einem solchen Fall kann
> ich doch die Dateigr��e nicht in einer Long-Variable speichern (hat ja auch
> nicht funktioniert)?

Klar. Allerdings gibts Systeme wo es gar keine Dateien gr��er als 2GB
gibt.

> Float ist auch ungeeignet, da eine exakte (positive) Ganzzahl herauskommen
> soll.
> Und wenn die maximale Gr��e einer Long Long Variable tats�chlich bei
> 9223372036854775807 liegt (8 Exabyte?), w�re dieser Datentyp doch eher
> geeignet, da ich davon ausgehe, dass mein Programm niemals mit einer solch
> gro�en Datei umgehen muss (sondern immer mit kleineren)?

Das Spiel kannst auch mit long und Files < 2GB spielen. :-)

Wie schon gesagt, warum willst du unbedingt long long nehmen, und
nicht einfach den daf�r vorgesehenen Datentyp? (Welcher das genau
ist, h�ngt von der Methode ab, mit der du die Filegr�sse ermitteln
willst).

>> Wirf das mal deinem compiler zu, vielleicht sagt das Ding was
>> zu den verwendeten Typen, vielleicht aber auch nicht:
>>
>> int vorsicht;
>>
>> vorsicht = ftell(...);
>
> error: invalid conversion from `void*' to `FILE*'|

Was �bergibst du denn an ftell? Die Meldung klingt danach, dass es
kein Filepointer ist, der von fopen zur�ckgeliefert wurde. Dann
kann das nat�rlich nicht funktionieren.

> Passt das denn in meine Funktion?

Was meinst du damit?

Tom

Claus Reibenstein

unread,
Nov 24, 2009, 4:09:07 PM11/24/09
to
Dominik Schmidt schrieb:

> ich bin neu in C/C++ (ich beschr�nke mich derzeit auf C++).

Dann bist Du hier falsch. Hier geht es nur um C, nicht um C++.

Versuch's mal nebenan in de.comp.lang.iso-c++.

Gru�. Claus

Message has been deleted

Marcel Müller

unread,
Nov 25, 2009, 3:45:41 AM11/25/09
to
Stefan Reuther wrote:
> Dominik Schmidt wrote:
>> In einem Beispiel habe ich gelesen, wie die Gr��e einer Datei ermittelt
>> wird, das Ergebnis wird in einer Integer-Variable gespeichert. Das
>> funktioniert nat�rlich hervorragend bei kleinen Dateien. Aber es gibt eine
>> Grenze (ich glaube etwa 2 GB?).
>
> Sei froh, unter DOS w�re die Grenze bei 32k :-)

Du meinst bei 16 Bit ints.
Aber selbst unter DOS war man schlau genug die Datei-Pointer als 32 Bit
auszulegen.

> Au�erdem gibt es fgetpos/fsetpos mit 'fpos_t', mit denen du dir zwar
> Positionen in beliebig gro�en Dateien merken kannst, wo du aber sonst


> portabel nicht allzuviel mit machen kannst.

Viele APIs bieten zus�tzliche Funktionen mit '64' hinten, um korrekt mit
gr��eren Files umzugehen.

> Abgesehen davon, dass C++ nach nebenan geh�rt: in C++ lautet der Typ f�r


> die Stream-Position 'istream::pos_type'.

Traurigerweise ist die iostream-Library oft die letzte, die auf 64 Bit
portiert wird und m.E. auch eines der eher dunklen und veralteten
Kapitel von C++.


Marcel

Thomas Koller

unread,
Nov 25, 2009, 3:55:43 AM11/25/09
to
Marcel M�ller <news.5...@spamgourmet.com> wrote:
> Stefan Reuther wrote:
>> Dominik Schmidt wrote:
>>> In einem Beispiel habe ich gelesen, wie die Gr��e einer Datei ermittelt
>>> wird, das Ergebnis wird in einer Integer-Variable gespeichert. Das
>>> funktioniert nat�rlich hervorragend bei kleinen Dateien. Aber es gibt eine
>>> Grenze (ich glaube etwa 2 GB?).
>>
>> Sei froh, unter DOS w�re die Grenze bei 32k :-)

> Du meinst bei 16 Bit ints.

Ja, das d�rfte die Breite eines int bei den meisten DOS-Compilern
gewesen sein.

> Aber selbst unter DOS war man schlau genug die Datei-Pointer als 32 Bit
> auszulegen.

Der OP hat ja explizit von "int" geschrieben. Es hilft dir nix wenn
du vom Datei-Pointer einen 32 Bit Wert (in dem Fall long) bekommst
und das Ergebnis dann einer 16 Bit Variablen (int) zuweist.

Auch wenn auf heutigen Systemen oft gilt sizeof(int) == sizeof(long),
das ist keine C-Garantie. Gerade bei Unix- oder Windowsprogrammen
sieht man aber immer wieder ein verlassen auf diese nicht garantierte
Annahme.

>> Au�erdem gibt es fgetpos/fsetpos mit 'fpos_t', mit denen du dir zwar
>> Positionen in beliebig gro�en Dateien merken kannst, wo du aber sonst
>> portabel nicht allzuviel mit machen kannst.
>
> Viele APIs bieten zus�tzliche Funktionen mit '64' hinten, um korrekt mit
> gr��eren Files umzugehen.

>> Abgesehen davon, dass C++ nach nebenan geh�rt: in C++ lautet der Typ f�r
>> die Stream-Position 'istream::pos_type'.
>
> Traurigerweise ist die iostream-Library oft die letzte, die auf 64 Bit
> portiert wird und m.E. auch eines der eher dunklen und veralteten
> Kapitel von C++.

Wobei der OP in der gl�cklichen Lage zu sein scheint, eine
Implementierung erwischt zu haben die es "richtig" macht.

Tom

Rainer Weikusat

unread,
Nov 25, 2009, 7:32:57 AM11/25/09
to
r...@zedat.fu-berlin.de (Stefan Ram) writes:

> Dominik Schmidt <dominik...@gmx.net> writes:
>>file1.seekg(0, ios::end);
>>Out1 = file1.tellg();
>
> In ISO/IEC 14882:2003(E), sind �seekg� und �tellg� wohl
> durch �pubseekoff� definiert, das auf �seekoff� basiert, was
> mit Hilfe von �::std::fseek� erkl�rt ist, das durch �fseek�
> aus ISO/IEC 9899:1990 definiert ist, welches aber bei
> bin�ren Str�men kein SEEK_END (entsprechend �::ios::end�)
> unterst�tzen mu�.

Aus Betriebssystemsicht sind Dateien nicht notwendigerweise
unstrukturierte Byte-Folgen und konsequenterweise gibt es ein Konzept
'Groesse einer Datei', repraesentierbar durch eine positive, ganze
Zahl, die die Anzahl der enthaltenen Bytes angibt, in C nicht.

Markus Wichmann

unread,
Nov 25, 2009, 3:02:32 PM11/25/09
to
Thomas Koller (tko...@gmx.at) schrieb:

> Marcel Müller <news.5...@spamgourmet.com> wrote:
>> Du meinst bei 16 Bit ints.
>
> Ja, das dürfte die Breite eines int bei den meisten DOS-Compilern
> gewesen sein.
>

Öhm... also, DJGPP benutzt IIRC 32 Bit dafür. Aber DJGPP ist ja auch ein
Sonderfall.

> Auch wenn auf heutigen Systemen oft gilt sizeof(int) == sizeof(long),
> das ist keine C-Garantie. Gerade bei Unix- oder Windowsprogrammen
> sieht man aber immer wieder ein verlassen auf diese nicht garantierte
> Annahme.
>

Das ist dann übrigens die Software, die am Sprung auf 64-bit-Prozessoren
scheitert: Wenigstens das System V ABI for AMD64 spezifiziert als
Programmiermodell LP64 (d.h. sizeof(int) == 4, sizeof(long) ==
sizeof(void*) == 8).

Übrigens gibt es auch Software, die unter der Annahme
sizeof(int)==sizeof(void*) läuft :-)

>> Viele APIs bieten zusätzliche Funktionen mit '64' hinten, um korrekt mit
>> größeren Files umzugehen.

Wieso die nicht gleich die return types umdefinieren können? Wegen der
Binär-Kompatibilität?

HTH,
Markus
--
Nur weil ein Genie nix reißt, muß ja nun nicht gleich jeder Idiot
pausieren... Bully hats ja auch geschafft.
-- gUnter nanonüm in de.alt.anime

0 new messages