Minimalen und Maximalen Wert ermitteln, den eine Variable aufnehmen kann
-
Hallo,
ich würde gerne
1. Von einem Variablentyp (z.B. int) den minimalen und maximalen Wert ermitteln, den eine Variable diesen Typs aufnehmen kann.
2. Von einer bereits deklarierten Variable den minimalen und maximalen Wert ermitteln, den diese Variable aufnehmen kann.Zu Punkt 1 hatte ich mir überlegt, dass ich da eigentlich einfach
2^(sizeof(int))
nehmen könnte. Dann noch geteilt durch zwei, und bei der einen Zahl ein minus davor. Ist mir aber eigentlich zu kompiliziert, und ich habe mir gedacht für so etwas gibt es doch bestimmt schon eine Funktion, so dass nicht jeder das Rad neu erfinden muss.
Zu Punkt 2 weiß ich momentan gar nicht wie ich das angehen soll.
Kann mir jemand einen Anstoß geben? Danke.
-
Zu 1. Binde den Header limits.h ein. Da gibt es Makros für die oberen/unteren Grenzen, z.B. INT_MAX, INT_MIN
Zu 2. Das wird nicht so einfach gehen. Aus mehreren Gründen. Du kannst zwar mit sizeof(object) die Größe einer Variablen in Bytes ermitteln und durch Multiplikation mit CHAR_BIT auch die Anzahl der Bits. Aber du kannst z.B. nicht ermitteln ob object überhaupt ein integer Typ ist, und selbst wenn, kannst du dessen signedness nicht ermitteln. Ferner kennst du nicht die interne Darstellung von Integern (du müsstest 2er-Komplement annehmen). Und so kann man das noch eine Weile weiterführen...
-
Hallo,
(1) für jede Variable vom Typ int wird eine bestimme Menge Speicher verwendet. Wird der Wert bei sukzessiver Inkrementation zu groß, sodass er nicht mehr in den Speicher passt, so nimmt die Variable plötzlich einen negativen Wert an (Überlauf). Dies können wir uns zu Nutze machen, um den größtmöglichen Werte zu bestimmen; dieses Vorgehen ist selbstverständlich nicht schnell und soll nur verdeutlichen.
(2) sizeof(int) liefert die Größe von int-Variablen als Vielfaches der Größe einer Variable vom Typ char (sizeof(char)=1), die genau aus CHAR_BIT Bits besteht. Wir haben also sizeof(int)*CHAR_BIT Bits. Bei mir sind das 32 Bit. Das bedeutet 31 Bit + Vorzeichenbit bei unsigned. Also:
2^31 = 2147483648
=> Werte aus [-2147483648; 2147483647]Beachte: Null ist hier eine positive Zahl, da VZB 0; deshalb nicht [-2147483648; 2147483648]!
Tim hat aber Recht, so einfach ist das nicht. In richtigen Programmen werden die Konstanten aus limits.h verwendet.
#include <stdlib.h> #include <stdio.h> #include <limits.h> int main() { /* kleinster und groesster Wert mittels einer Schleife durch ausprobieren bestimmen */ int i = 0; while (++i > 0) ; printf("kleinster Wert:\t%i\n", i); printf("größter Wert:\t%i\n", --i); /* Ausgabe sizeof(int) und CHAR_BIT */ printf("sizeof(int):\t%i\n", (int)sizeof(int)); printf("CHAR_BIT:\t%i\n", CHAR_BIT); return EXIT_SUCCESS; }
-
lucky_tux schrieb:
(1) für jede Variable vom Typ int wird eine bestimme Menge Speicher verwendet. Wird der Wert bei sukzessiver Inkrementation zu groß, sodass er nicht mehr in den Speicher passt, so nimmt die Variable plötzlich einen negativen Wert an (Überlauf). Dies können wir uns zu Nutze machen, um den größtmöglichen Werte zu bestimmen; dieses Vorgehen ist selbstverständlich nicht schnell und soll nur verdeutlichen.
Ganz abgesehen von der Schnelligkeit, dieses Verfahren ist nicht zu empfehlen, da signed integer overflows in ihrem Verhalten nicht definiert sind. Ein kleiner Test könnte das verdeutlichen:
Gegeben sei folgendes Programm:
#include <stdio.h> int get_max_int (void) { int i = 0; while (i < i+1) { i++; } return i; } int main (void) { printf ("%d", get_max_int()); return 0; }
Die Funktion get_int_max() soll uns den maximal darstellbaren Wert eines int liefern, eben mit der von dir beschriebenen Methode. Kompiliert wird erstmal ohne Optimierung:
tim@onyx:~/src/c$ gcc overflow.c -o overflow -Wall -Wextra -pedantic -O0
Kein Fehler, keine Warnung. Scheint alles glatt zu laufen. Führen wir das Programm aus:
tim@onyx:~/src/c$ time ./overflow 2147483647 real 0m7.301s user 0m7.300s sys 0m0.000s
Nach ~sieben Sekunden teriniert das Programm und der (auf 32Bit-Systemen) erwartete Wert wird ausgegeben.
Gemein wie wir sind, probieren wir das aber noch mit etwas stärkerer Optimierung:
tim@onyx:~/src/c$ gcc overflow.c -o overflow -Wall -Wextra -pedantic -O3 overflow.c: In Funktion »get_max_int«: overflow.c:5: [b]Warnung: assuming signed overflow does not occur when assuming that (X + c) > X is always true[/b]
Oha... trotzdem mal testen:
tim@onyx:~/src/c$ time ./overflow
...
7 Sekunden vorbei
...
1 Minute vorbei
...
2 Minuten vorbei... ich denke hier kann man sagen, dass das Programm so schnell nicht terminieren wirdlucky_tux schrieb:
2^31 = 2147483648
=> Werte aus [-2147483648; 2147483647]Beachte: Null ist hier eine positive Zahl, da VZB 0; deshalb nicht [-2147483648; 2147483648]!
Genau genommen kannst du dir bei der Rechnung nicht sicher sein, ob das zugrundeliegende System überhaupt mit 2er-Komplement rechnet. Es könnte z.B. auch eine sign+magnitude-Darstellung sein, da wären die Grenzen [-2147483647... 2147483647].
PS:
gcc-Version 4.2.3 (Ubuntu 4.2.3-2ubuntu7)
PPS: in deinem Programm passiert bei mir mit -O3 fast dasselbe, nur kommt da fieserweise keine Warnung mehr.
-
man kann's auch ausrechnen, wenn <limits.h> nicht da ist. z.b.
int max = (int)((unsigned int)-1/2); int min = -(int)max-1;
-
auch sehr zu empfehlen: http://www.fefe.de/intof.html