-2147483648
-
Daniel E. schrieb:
JensE schrieb:
Es steht eben genau das drin, was SG1 über die Vorgehensweise des MSVC++ Compilers gesagt hat: Zuerst die Zahl, dann das Minus.
Schon komisch.Nein.
Doch! Lies einfach mal an der angegebenen Stelle nach.
Daniel E. schrieb:
In der aktuellen Norm, also C99, wird das Literal 2147483648 bei deiner Systemkonfiguration einem long long zugeschlagen, und dann das Minus darauf angewendet. Dann bekommt man eine negative Zahl vom Typ long long, die aber in einen long reinpasst.
Soweit ist das klar.
Daniel E. schrieb:
Nun zufrieden? Dann brauchst Du nur noch einen aktuellen Compiler (und den Code geringfügig anpassen).
Also ist VC++ 6.0 + neuestes Service-Pack nicht aktuell? Und wie soll ich den Code geringfügig anpassen?
Und erklär mir das mal:
signed __int64 a = -2147483648; // hier kommt die oben genannte Warnung signed __int64 b = -2147483647; // hier nicht mehr signed __int64 c = -4294967295; // hier kommt auch die Warnung signed __int64 d = -4294967296; // hier kommt sie nicht mehr
Soll heißen alle Zahlen zwischen -2147483648 und -4294967295 behandelt mein Compiler immer als positiv.
Grüße
Jens
-
JensE schrieb:
Daniel E. schrieb:
JensE schrieb:
Es steht eben genau das drin, was SG1 über die Vorgehensweise des MSVC++ Compilers gesagt hat: Zuerst die Zahl, dann das Minus.
Schon komisch.Nein.
Doch! Lies einfach mal an der angegebenen Stelle nach.
Ich habe den Thread gelesen und sogar schon auf der ersten Seite die Erkläung gepostet. Komisch ist an diesem Verhalten nichts.
Daniel E. schrieb:
Nun zufrieden? Dann brauchst Du nur noch einen aktuellen Compiler (und den Code geringfügig anpassen).
Also ist VC++ 6.0 + neuestes Service-Pack nicht aktuell? Und wie soll ich den Code geringfügig anpassen?
VC 6 kommt aus der Steinzeit (1995 oder so, nicht?). Ein Servicepack macht meiner Erinnerung nach die gröbsten Bugs raus und bringt vielleicht ein paar kleine Features mit. C99 verlangt aber normalerweise einen vollständig reimplementierten Compiler.
Anpassen müßtest Du deine printf-Aufrufe, weil Du einen long long anders ausgeben mußt, als einen int, was auf der ersten Blick einsichtig sein sollte.
Und erklär mir das mal:
signed __int64 c = -4294967295; // hier kommt auch die Warnung signed __int64 d = -4294967296; // hier kommt sie nicht mehr
Soll heißen alle Zahlen zwischen -2147483648 und -4294967295 behandelt mein Compiler immer als positiv.
4294967296 passt nicht mehr in einen unsigned long, also versucht der Compiler gar nicht erst, ihn da reinzustecken und warnt auch nicht. Wo ist das Problem?
-
Das Problem ist, dass z.B. die Zahl -4294967295 als 4294967295 behandelt wird.
Wenn ich beispielsweise schreibe -4294967295 / 10, kommt 0 raus (weil er diese Zahl als 1 oder so interpretiert), und nicht -429496729.
Also wie bei der kleinsten long Zahl.
Nur sehe ich nicht ein, warum er das hier macht, das ist doch nun echt absolut schwachsinnig: Wenn ich ihm nun sag, ich verwende signed __int64, warum will er die Zahl nicht so behandeln, wie ich sie hinschreib?Ist das für dich also vollkommen normal? Machst du dann in Code, der signed __int64 verwendet, sowas:
if (a < -2147483647 && a > -4294967296) b = - (a / 10); else b = a / 10;
-
Daniel E. schrieb:
Daniel E. schrieb:
Nun zufrieden? Dann brauchst Du nur noch einen aktuellen Compiler (und den Code geringfügig anpassen).
Also ist VC++ 6.0 + neuestes Service-Pack nicht aktuell? Und wie soll ich den Code geringfügig anpassen?
VC 6 kommt aus der Steinzeit (1995 oder so, nicht?).
Nee, der MSC 6 ist von 1998. Ist aber trotzdem mehr als alt und der aktuelle Standard war damals auch noch nicht fix. Aktuelle ist der MSC 8.
JensE schrieb:
Das Problem ist, dass z.B. die Zahl -4294967295 als 4294967295 behandelt wird.
Wenn ich beispielsweise schreibe -4294967295 / 10, kommt 0 raus (weil er diese Zahl als 1 oder so interpretiert), und nicht -429496729.
Du hast recht, diese wird auch als 1 interpretiert. Das ist aber auch logisch, da Integer Literale ohne Spezifizierung imer vom Typ int sind. Willst du etwas anderes, musst du entsprechende Suffixe verwenden, zB
long long a = -4294967295ll / 10;
Da der MSC 6 aber wie gesagt schon ziemlich alt ist, unterstützt der keinen Typ long long (nur __int64) und vermutlich auch kein ll Suffix (aber wahrscheinlich etwas vergleichbares).
-
Anscheinend gibt es keinen solchen Suffix für MSVC++ 6.0.
Gut, da ich Methoden haben, die signed __int64 übergeben bekommen, muss ich also quasi dem Anwender sagen:
"Übergib Konstanten immer mit dem entsprechenden Suffix, sonst werden sie von bestimmten Compilern eventuell anders interpretiert."
Wenn ich mir dann irgendwann mal einen neueren Compiler zulege, nehm ich ja dann sowieso den plattformunabhängigen Typ long long.
Also ich nehme aus dieser Diskussion mit:
- Alle Zahlen sind für den Compiler erstmal ints, wenn sie kleiner gleich 2^32 - 1 sind, egal, ob da noch ein Minus davor steht
- Wenn aber ein Minus davorsteht, sind die Zahlen von -2147483648 bis -4294967295 zu klein, um als signed int angesehen zu werden, also nimmt er sie positiv
- Um das zu vermeiden, müsste man einen Suffix verwenden, wenn es ihn gäbe
- Alle Zahlen größer als 4294967295 werden eben immer als __int64 genommenSo in etwa habe ich das jetzt alles verstanden. Korrigiert mich bitte, wenn ich da falsch liege.
Warum das so geregelt wurde, ist mir aber noch nicht so richtig klar, und warum das nirgendswo ordentlich dokumentiert wurde, auch nicht.
-
JensE schrieb:
- Um das zu vermeiden, müsste man einen Suffix verwenden, wenn es ihn gäbe
Diese Suffixe gibt es.
u U - unsigned
l L - long
ll LL - long longSo werden sie vom Standard definiert. Lediglich ältere Compiler werden wohl ll LL nicht unterstützen.
JensE schrieb:
- Alle Zahlen größer als 4294967295 werden eben immer als __int64 genommen
Diese Regelung ist mir ehrlich gesagt unbekannt.
-
groovemaster schrieb:
Diese Suffixe gibt es.
u U - unsigned
l L - long
ll LL - long longSo werden sie vom Standard definiert. Lediglich ältere Compiler werden wohl ll LL nicht unterstützen.
Ja, bei meinem VC++ 6.0 gibt es ll und LL nicht. Auch für __int64 gibt es wohlgemerkt keinen microsoft-spezifischen Suffix.
groovemaster schrieb:
JensE schrieb:
- Alle Zahlen größer als 4294967295 werden eben immer als __int64 genommen
Diese Regelung ist mir ehrlich gesagt unbekannt.
Naja, ich meine damit: Wie parst er denn beispielsweise diese Zeile?
signed int __64 = -42949672950;
Er wird ja -wie von anderen bereits gesagt wurde - zuerst die Zahl betrachten. Und jetzt merkt er: AHA, größer als LONG_MAX. Also denkt er sich, der Suffix (wenn es einen gäbe) ist hier überflüssig, und keine Warnung kommt, er nimmt die Zahl so, wie sie ist.
-
JensE schrieb:
groovemaster schrieb:
JensE schrieb:
- Alle Zahlen größer als 4294967295 werden eben immer als __int64 genommen
Diese Regelung ist mir ehrlich gesagt unbekannt.
Naja, ich meine damit: Wie parst er denn beispielsweise diese Zeile?
signed int __64 = -42949672950;
Er wird ja -wie von anderen bereits gesagt wurde - zuerst die Zahl betrachten. Und jetzt merkt er: AHA, größer als LONG_MAX. Also denkt er sich, der Suffix (wenn es einen gäbe) ist hier überflüssig, und keine Warnung kommt, er nimmt die Zahl so, wie sie ist.
__int64 ist kein Teil von C, d.h. der Compiler kann machen, was er will.
In C99 mit long long arbeitend, läßt ein Ausdruck wie 9223372036854775808ll (= -LLONG_MIN) den Typ long long überlaufen, also hat man es formal mit undefiniertem Verhalten zu tun. Bei handelsüblichen Rechnern, die Zahlen im Zweierkomplement darstellen, kommt also bei -92...8ll aber überraschenderweise wirklich LLONG_MIN heraus. Eine Garantie dafür gibt es aber nicht, wenn ich nichts übersehen habe.
-
Okay,
vielen Dank für die umfangreichen Antworten, hat mich wirklich weiter gebracht.