size_t Overflow erkennen
-
DrakoXP schrieb:
Bei mir kommt dabei die Frage auf: wie lösen die in C das Problem?
Welches Problem? Das theoretische? Nein, in C lösen wir doch lieber reale

-
pumuckl schrieb:
plizzz schrieb:
Kurze Frage noch: Ist es eigentlich möglich, einen Array anzulegen, der mehr Einträge hat, als man mit dem Typen size_t darstellen kann?
AFAIK nicht, nein.
Gibt es nicht irgendwann bei solchen extremen Größen Probleme mit der Adressierung?
Würde es geben. Aus dem Grund ist size_t so gut wie immer sowas wie unsigned int, hat also je nach Betriebssystem auf "normalen" PCs 32 oder 64 bit. Aus dem Grund sind jetzt auch die 64bit Systeme im Kommen, weil man mit 32 bit eben nur <4GB Speicher adressieren kann.
Edit: Kann ich mir überhaupt sicher sein, dass beim Umgang eines Arrays mit max size_t vielen Einträgen (Objekten) alles gut geht (abgesehen davon, dass der physische Speicher recht schnell voll sein wird)?
Abgesehen davon dass du so viel Speicher vermutlich nicht wirst anfordern können, kannst du dir sicher sein, dass du damit ganz normal arbeiten kannst, wenn du ihn erstmal hast. Natürlich mit entsprechenden Performanceproblemen...
Ah okay, das heißt dann also, dass ich insgesamt nur sizeof(size_t) viele Bytes an Speicher überhaupt adressieren kann (ist das die "Definition" von size_t ?)?
-
std::size_t kann schlicht für alle Speichergrößen verwendet werden und ist eigentlich immer exakt so groß, um jedes Byte das der Prozessor addressieren kann auch selbst darstellen könnte. Wären unter 64bit immerhin 16.777.216 Terrabyte, also genug.

-
Ethon schrieb:
std::size_t kann schlicht für alle Speichergrößen verwendet werden und ist eigentlich immer exakt so groß, um jedes Byte das der Prozessor addressieren kann auch selbst darstellen könnte. Wären unter 64bit immerhin 16.777.216 Terrabyte, also genug.

Muß nicht sein. Stell Dir DOS vor mit einem Speichermodell, wo kein Objekt größer als 64k sein kann, aber Zeiger 32-bittig sind.
Desdawegen ist ja auch die Adressvergleicherei in C++ nicht garantiert, wenn man Zeiger aus verschiedenen Objekten vergleicht.Aber faktisch kann man davon ausgehen. Da reicht es sogar, wie ich eingangs sagte, gegen 0 zu prüfen (also (sizeof(Element)<<n)==0 mit einer Zweierpotenz als sizeof(Element)).
-
volkard schrieb:
Da reicht es sogar, wie ich eingangs sagte, gegen 0 zu prüfen (also (sizeof(Element)<<n)==0 mit einer Zweierpotenz als sizeof(Element)).
Nicht zu empfehlen.
C++11 schrieb:
5.8 Shift operators [expr.shift]
1 The shift operators << and >> group left-to-right.
shift-expression:
additive-expression
shift-expression << additive-expression
shift-expression >> additive-expression
The operands shall be of integral or unscoped enumeration type and integral promotions are performed.
The type of the result is that of the promoted left operand. The behavior is undefined if the right operand
is negative, or greater than or equal to the length in bits of the promoted left operand.
-
Danke schonmal für die vielen Antworten, der Thread hat mir schon ein wenig geholfen, mein Wissen zu erweitern.
Noch eine kurze Frage zu dem <<-Operator. Wie verhält es sich hier mit impliziten Typedefs?
Angenommen: Ich schreibe a << b, wobei a ein Short ist und b ein unsigned long? Das hat insofern Relevanz, dass der Ausdruck bei short einen Overflow geben könnte, während er bei unsigned long keine Probleme verursacht. Was ist, wenn ich links ein Literal stehen habe? Welchen Typ hat dann der Ausdruck 1<<n? Kann ich davon ausgehen, dass er den gleichen Typ hat wie n?
Die gleiche Frage stellt sich bei mir gerade mit Addition:
Angenommen, ich habe eine int a und eine unsigned long b und berechne a + b. Eigentlich müsste das Ergebnis Typ int haben, da dabei eben auch negative Werte auftreten können. Wäre andererseits aber etwas paradox, denn man könnte dann ja einfach Overflows produzieren, selbst wenn a zB den Wert 0 hat (und b größer als max_int ist).Übrigens kann man sich das mit CHAR_BITS wohl auch sparen, wenn man die Funktion digits aus limits.h benutzt: [Return-Wert] For integer types: number of non-sign bits (radix base digits) in the representation.
-
plizzz schrieb:
Angenommen, ich habe eine int a und eine unsigned long b und berechne a + b. Eigentlich müsste das Ergebnis Typ int haben, da dabei eben auch negative Werte auftreten können.
Der Typ ist unsigned long.
Die Regeln nach denen das abläuft stehen z.B. hier:
http://msdn.microsoft.com/en-us/library/09ka8bxx(v=VS.80).aspx
-
Okay danke. DAs ist gut zu wissen und ergibt Sinn.
-
Ich grade den Thread mal wieder aus. Und zwar ist es nun so, dass size_t bei mir 32 bits groß ist, ich allerdings ein 64-Bit System habe. Steht das nicht im Widerspruch zur Idee von size_t?
-
plizzz schrieb:
Ich grade den Thread mal wieder aus. Und zwar ist es nun so, dass size_t bei mir 32 bits groß ist, ich allerdings ein 64-Bit System habe. Steht das nicht im Widerspruch zur Idee von size_t?
Du kompilierst im 64bit Modus?
-
Darüber habe ich mir noch gar keine Gedanken gemacht - ich kompiliere einfach, sozusagen. Aber das wird dann wohl nicht der 64bit Modus sein und damit ist die Frage dann geklärt. Heißt das dann auch, dass so Dinge wie sizeof(Datentyp), CHAR_BIT, INT_MAX, ... beim Zeitpunkt der Kompilierung und nicht während der Laufzeit festgelegt werden?
-
plizzz schrieb:
Darüber habe ich mir noch gar keine Gedanken gemacht - ich kompiliere einfach, sozusagen. Aber das wird dann wohl nicht der 64bit Modus sein und damit ist die Frage dann geklärt. Heißt das dann auch, dass so Dinge wie sizeof(Datentyp), CHAR_BIT, INT_MAX, ... beim Zeitpunkt der Kompilierung und nicht während der Laufzeit festgelegt werden?
ja
-
Ethon schrieb:
Wären unter 64bit immerhin 16.777.216 Terrabyte, also genug.

Das heißt Terabyte und nicht Terrabyte.
-
plizzz schrieb:
Welchen Typ hat dann der Ausdruck 1<<n? Kann ich davon ausgehen, dass er den gleichen Typ hat wie n?
Hier greift die arithmetic promotion, defaultmäßig rechnet C mit int.
Nein. Deshalb verwendet man sinnigerweise auch 1UL<<n bzw. 1ULL<<n.
-
Wutz schrieb:
Das heißt Terabyte und nicht Terrabyte.
Dafür gibts mal ein fettes +1.
-
Wutz schrieb:
plizzz schrieb:
Welchen Typ hat dann der Ausdruck 1<<n? Kann ich davon ausgehen, dass er den gleichen Typ hat wie n?
Hier greift die arithmetic promotion, defaultmäßig rechnet C mit int.
Nein. Deshalb verwendet man sinnigerweise auch 1UL<<n bzw. 1ULL<<n.Vielen Dank für den Hinweis. Ich kannte die Typbestimmungen bei Literalen gar nicht.