Hallo, ist eigentlich im C-Standard festgelegt, was bei einem Überlauf der verschiedenen Datentypen als nächster Wert herauskommt? Also was für ein Wert erhalte ich nach einem Überlauf durch z.b. i++ bei: int unsigned int char unsigned char Ich brauche in einem Timerinterrupt einen Zähler der immer durchläuft. Oder sollte man des Stils wegen auf die Einhaltung des Wertebereichs prüfen und dann manuell wieder von vorn beginnen?
Hi, Thomas, wenn Du aufwärts zählst und am Ende des Wertebereiches angekommen bist, dann führt der nächste Schritt ans andere Ende. Srell Dir den Wertebereich wie das Zifferblatt einer Uhr vor - nach 23 Uhr kommt 0 Uhr. Dein Zähler läuft also sowieso immer durch. Gelegentlich kann man Überlauf nicht brauchen. Dann nehme ich zwei Variablen, die ich beide auf diesem Ziffernblatt um 90° versetzt weiterzähle. Ciao Wolfgang Horn
> ist eigentlich im C-Standard festgelegt, was bei einem Überlauf > der verschiedenen Datentypen als nächster Wert herauskommt? Bei vorzeichenlosen ja. Da werden alle Berechnungen immer Modulo 2 hoch Bitzahl durchgeführt. Wenn man oben rausläuft, kommt man unten wieder rein. Bei den Typen mit Vorzeichen ist es undefiniert. > Also was für ein Wert erhalte ich nach einem Überlauf durch z.b. > i++ bei: > > int undefiniert > unsigned int 0 > char implementationsspezifisch > unsigned char 0
"ist eigentlich im C-Standard festgelegt, was bei einem Überlauf der verschiedenen Datentypen als nächster Wert herauskommt?" Ber Typen ohne Vorzeichen ja. Modulo (<maximaler Wert>+1). Ist das was man intuitiv auch erwartet. Bei Typen mit Vorzeichen ist das Verhalten bei Überlauf offiziell undefiniert.
Noch ne Gemeinheit, bei int ist die Länge undefiniert. Statt int sollte man daher besser short (16Bit) nehmen, da auf 32Bittern int = long (32Bit) ist. Peter
> Noch ne Gemeinheit, bei int ist die Länge undefiniert. Generell ist bei allen ,,allgemeinen Typen'' die Länge undefiniert. Es gibt nur Mindestanforderungen an die Genauigkeit, die bei unseren üblichen Zweierkomplementdarstellungen und IEEE754-Gleitkommazahlen folgendes implizieren: . sizeof(char) >= 8 . sizeof(short) >= 16 . sizeof(int) >= 16 . sizeof(long) >= 32 . sizeof(long long) >= 64 . sizeof(float) >= 32 . sizeof(double) > 32 (Letzteres wird vom AVR-GCC derzeit nicht eingehalten.) > Statt int sollte man daher besser short (16Bit) nehmen, da auf > 32Bittern int = long (32Bit) ist. Nein, wenn man Typen mit expliziten Längen haben möchte, sollte man auch Typen mit expliziten Längen benutzen, statt implizite Annahmen zu treffen. Diese sind (per C99) in <stdint.h> definiert. Wenn eine Maschine dann z. B. keinen 8-Bit-Datentyp kennt (soll's bei einigen DSPs geben), dann bekommt man wenigstens saubere Fehler beim Versuch, int8_t oder uint8_t zu benutzen (die gibt's dort dann nicht), statt irgendwelcher Überraschungen, weil der Programmierer implizit angenommen hat, dass sein "unsigned char" genau 8 Bits lang wäre und von 255 nach 0 umschlägt.
Immerhin gibt es auch eine Headerdatei, die die Grenzen der vor C99 definierten Datentypen beschreibt - limits.h Auszug aus limits.h des mit Rowley Crossworks for ARM gelieferten gcc:
1 | #define CHAR_BIT 8
|
2 | #define CHAR_MAX 255
|
3 | #define CHAR_MIN 0
|
4 | #define SCHAR_MAX 127
|
5 | #define SCHAR_MIN (-128)
|
6 | #define UCHAR_MAX 255
|
7 | #define SHRT_MAX 32767
|
8 | #define SHRT_MIN (-32767 - 1)
|
9 | #define USHRT_MAX 65535
|
10 | |
11 | #if defined(__CROSSWORKS_MSP430) || defined(__CROSSWORKS_AVR) ||
|
12 | defined(__CROSSWORKS_MAXQ) |
13 | #define INT_MAX 32767
|
14 | #define INT_MIN (-32767 - 1)
|
15 | #define UINT_MAX 65535
|
16 | #else
|
17 | #define INT_MAX 2147483647
|
18 | #define INT_MIN (-2147483647 - 1)
|
19 | #define UINT_MAX 4294967295
|
20 | #endif
|
21 | |
22 | #define LONG_MAX 2147483647
|
23 | #define LONG_MIN (-2147483647 - 1)
|
24 | #define ULONG_MAX 4294967295
|
25 | #define LLONG_MIN (-9223372036854775807LL - 1)
|
26 | #define LLONG_MAX 9223372036854775807LL
|
27 | #define ULLONG_MAX 18446744073709551615ULL
|
Damit kann man sich also auch mit nicht-C99-Compilern behelfen; eine vergleichbare Datei existiert beispielsweise auch bei MS-Compilern, die älter sind als C99.
> Noch ne Gemeinheit, bei int ist die Länge undefiniert. Sie ist nicht undefiniert, sondern implementationsspezifisch. > Statt int sollte man daher besser short (16Bit) nehmen, da auf > 32Bittern int = long (32Bit) ist. short und long sind genauso implementationsspezifisch wie int. Zur Ergänzung von Rufus' Posting: C99 bietet mit stdint.h einen Header, der typedefs unter anderem für Integertypen mit festen Größen bietet. Es ist übrigens ein Armutszeugnis für die Compilerhersteller, wenn sie es nach 7 Jahren immer noch nicht geschafft haben, halbwegs ISO-konforme Compiler zu bauen. C89 ist keine Norm, denn es wurde mit Erscheinen von C99 offiziell ungültig.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.