-2147483648



  • JensE schrieb:

    wie ihr sicher erkennt, ist das -2^31. Wenn ich den Wert meiner Variablen zuweise

    signed long int a = -2147483648;
    

    kommt die Warnung:

    "warning C4146: Einem vorzeichenlosen Typ wurde ein unaerer Minus-Operator zugewiesen; das Ergebnis ist weiterhin vorzeichenlos"

    Eigentlich steht die Lösung für dein Problem genau hier.
    2147483648 ist offensichtlich ein großer int-Wert. Sogar so groß, daß er nicht mehr in einen gewöhnlichen int hineinpaßt. Der Compiler denkt sich also 2147483648 sei eine unsigned-Zahl (da paßt es hervorragend rein), und wendet das unäre Minus auf die Zahl an.

    printf("MOD1: %d\n", (-2147483648 % 10));   // ergibt 8
    

    Hier das gleiche: -2147483648 ist eine positive Zahl, von der moduloisierst.
    Wenn Du hier a%10 geschrieben hätttest, dann bekommst Du wahrscheinlich was anderes raus, oder?

    Würgaround: Diese Zahl nicht direkt hinschreiben, sondern LONG_MIN, (-2147483647 - 1) oder was kreativeres benutzten.



  • Ich hab gerade mal in meiner limits.h nachgeschaut und da steht tatsächlich

    #define LONG_MIN (-2147483647L - 1)
    

    Seltsamerweise scheint sowas zB bei short nicht notwendig zu sein

    #define SHRT_MIN (-32768)
    

    Schon irgendwie seltsam. 😕



  • 32768 lässt sich doch auch (zumindest auf 32bit-Architekturen) wunderbar als int darstellen.



  • SG1 schrieb:

    32768 lässt sich doch auch (zumindest auf 32bit-Architekturen) wunderbar als int darstellen.

    Aber eben nicht als short, -32768 hingegen schon. Und das gleiche trifft eben auch auf long mit -2147483648 bzw. 2147483648 zu.



  • Ist zu dem Zeitpunkt aber irrelevant. 32768 ist vom Typ int.



  • Na und? Auf einem 16-Bit System kann int halt auch nur 16 Bit breit sein. Die Frage ist ja, warum -2147483648 nicht als 32 Bit int vom Compiler akzeptiert wird.



  • Die Zahl ist doch 2312^{31} müsste das nicht 23112^{31}-1 sein?

    bye

    tt



  • groovemaster schrieb:

    Na und? Auf einem 16-Bit System kann int halt auch nur 16 Bit breit sein.

    ok, da würde das ganze natürlich nicht funktionieren

    Die Frage ist ja, warum -2147483648 nicht als 32 Bit int vom Compiler akzeptiert wird.

    Weil das ganze 2 Tokens sind: '-' '2147483648'. Letzteres ist keine als int darstellbare Zahl, also ist der Typ unsigned int.



  • Ich hab da weitere komische Sachen rausgefunden. In VC++ gibts ja den Typ signed __int64.
    Mit der kleinstmöglichen Zahl bringt er mir da dieselbe Warnung:

    signed __int64 a = -9223372036854775808;
    

    Für viele größere negative Zahlen kommt der Fehler nicht, aber komischerweise für den Bereich:

    -4294967295 bis -2147483648
    

    Für diese signed __int64-Zahlen bringt er die Warnung wieder!

    Seltsam.



  • SG1 schrieb:

    Weil das ganze 2 Tokens sind: '-' '2147483648'. Letzteres ist keine als int darstellbare Zahl, also ist der Typ unsigned int.

    Was meinst du mit "keine als int darstellbare Zahl"???
    Sie liegt nun mal im maximal möglichen Bereich.
    Die Warnung bedeutet wohl eher, dass er eine solche negative Zahl nicht handeln kann, warum auch immer, und deshalb ihr Zweierkomplement verwendet, was ja auch wirklich bei Division und Modulo geschieht. printf() haben aber kein Problem damit.



  • JensE schrieb:

    SG1 schrieb:

    Weil das ganze 2 Tokens sind: '-' '2147483648'. Letzteres ist keine als int darstellbare Zahl, also ist der Typ unsigned int.

    Was meinst du mit "keine als int darstellbare Zahl"???
    Sie liegt nun mal im maximal möglichen Bereich.

    Nein, 2147483648 ist genau 1 zu gross. Erst DANACH wird das - angewendet.



  • Also hat es was damit zu tun, wie der Compiler den Code parst? Erzähl mir mehr darüber, ich will den genauen Grund erfahren!



  • SG1 schrieb:

    Nein, 2147483648 ist genau 1 zu gross. Erst DANACH wird das - angewendet.

    Es bimmelt langsam: 2147483648 ist ja um 1 größer als die größte signed long int Zahl. Das hättest du noch dazu sagen müssen, dann wäre es schneller gegangen 🙂

    Allerdings versteh ich nicht, warum der Compiler so "dumm" ist. Und erklär mir einer das, was ich zwei Posts drüber zum besten gegeben habe, ich darf mich kurz mal selbst zitieren:

    JensE schrieb:

    Ich hab da weitere komische Sachen rausgefunden. In VC++ gibts ja den Typ signed __int64.
    Mit der kleinstmöglichen Zahl bringt er mir da dieselbe Warnung:

    signed __int64 a = -9223372036854775808;
    

    Für viele größere negative Zahlen kommt der Fehler nicht, aber komischerweise für den Bereich:

    -4294967295 bis -2147483648
    

    Für diese signed __int64-Zahlen bringt er die Warnung wieder!

    Seltsam.

    Das mit der kleinsten signed int-64 ist ja wieder verständlich, aber der Bereich -4294967295 bis -2147483648 ist verwirrend.
    Kann ja nur daran liegen, dass der Compiler das eben als signed long int versucht zu interpretieren, und nicht als signed __int64.



  • SG1 schrieb:

    Die Frage ist ja, warum -2147483648 nicht als 32 Bit int vom Compiler akzeptiert wird.

    Weil das ganze 2 Tokens sind: '-' '2147483648'. Letzteres ist keine als int darstellbare Zahl, also ist der Typ unsigned int.

    Nun, soweit waren wir ja schon. Das ist schon klar. Nur warum parst ein Compiler so dämlich. Wenn er mir schon signed Integer Typen anbietet, dann möchte ich doch bitte auch entsprechende Literale verwenden können. Ich sage ihm doch nicht, nehme 2147483648 und negiere, sondern nehme -2147483648. Verstehst du was ich meine?



  • Ich bin genau groovemasters Meinung!

    Warum wird die Zahl -2147483648 überhaupt bereitgestellt, wenn man sie nicht wie alle anderen auch verwenden kann?

    Das hat sicher einen guten Grund, es ist nur die Frage, welcher das ist.
    Zumindest wird auch in limits.h jeweils die kleinste Zahl eines Bereiches geschickt umgangen, eben mit LONG_MIN.



  • Hab einen ähnlichen Artikel in der MSDN knowledge base darüber gefunden,

    gebt einfach mal "PRB: Can't Set Certain DataTypes to Minimum Documented Value" bei "Suchen" ein und der Artikel müsste erscheinen.

    da ist kurz beschrieben, wie MS Visual Basic mit den kleinsten Zahlen umgeht...

    Es steht eben genau das drin, was SG1 über die Vorgehensweise des MSVC++ Compilers gesagt hat: Zuerst die Zahl, dann das Minus.
    Schon komisch.



  • 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. Der Compiler kann ja nicht wissen, was Du meinst. Die Mehrheitsmeinung der C-Gurus zu dem Thema war offenbar schwankend. 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. Nun zufrieden? Dann brauchst Du nur noch einen aktuellen Compiler (und den Code geringfügig anpassen).

    Warum wird die Zahl -2147483648 überhaupt bereitgestellt, wenn man sie nicht wie alle anderen auch verwenden kann?

    Sie wird haargenau wie alle anderen "bereitgestellt". -3 ist auch die Zahl 3, und darauf ein Minus angewendet. Die Sprachbeschreibung sieht negative Integerkonstanten nur über diesen Umweg vor. Da es aber normalerweise im Wertebereich eines long genau eine Zahl mehr im negativen, als im positiven Bereich gibt, hat man eben in C89 diesen etwas seltsamen Effekt, von denen C aber durchaus noch mehr zu bieten hat.



  • 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;
    

Anmelden zum Antworten