2016-03-21 21 views
0

Ich versuche Gleichheit und ohne Vorzeichen Versionen von short, int und lange in C. Insbesondere zu testen, habe ich den folgenden Testcode verwendet:inkonsistent Gleichheit und ohne Vorzeichen nach Überlauf in C

#include <stdio.h> 

int main() { 
    signed short ss = 0x8000; // 2^15 
    unsigned short us = 0x8000; 
    printf("ss = %i, us = %i\n", ss, us); 
    if (ss == us) { printf("ss == us\n"); } 
    else { printf("ss != us\n"); } 

    signed int si = 0x80000000; // 2^31 
    unsigned int ui = 0x80000000; 
    printf("si = %i, ui = %i\n", si, ui); 
    if (si == ui) { printf("si == ui\n"); } 
    else { printf("si != ui\n"); } 

    signed long sl = 0x8000000000000000L; // 2^63 
    unsigned long ul = 0x8000000000000000UL; // 2^63 
    printf("sl = %li, ul = %lu\n", sl, ul); 
    if (sl == ul) { printf("si == ui\n"); } 
    else { printf("sl != ul\n"); } 
} 

der Code gibt der folgende:

ss = -32768, us = 32768 
ss != us 
si = -2147483648, ui = -2147483648 
si == ui 
sl = -9223372036854775808, ul = 9223372036854775808 
si == ui 

Also für Shorts sie nicht gleich sind, sondern auch für die beiden anderen sind sie. Ist etwas nicht in Ordnung mit dem, was ich annehme, oder ist das nur eine bekannte Eigenart von C?

+0

Das ist keine Eigenart, sondern Standardverhalten. – Olaf

+0

In den 'printf'-Anweisungen wird nicht wie in' Like 'verglichen: In den ersten beiden (aber nicht im dritten Beispiel) verwenden Sie '% i' (signed int) sowohl für die vorzeichenbehafteten als auch die vorzeichenlosen Werte, die die Daten ausgeben auf den Stapel gelegt, wie es gesagt wird. Sobald es dort ist, gibt es keine Möglichkeit zu sagen, ob sie signiert oder nicht signiert sind, abgesehen von ihrem Kontext. Im Fall der 'short' werden die Werte vor dem Platzieren auf dem Stapel zu 'signed int' und 'unsigned int' (wegen des Variablentyps) hochgestuft und dann wegen des'% ich bin Spezifizierer. –

Antwort

0

Ausgabe Gegeben sind die short und unsigned short kleiner als int. Beide werden für den ersten Vergleich in int konvertiert und die konvertierten Werte unterscheiden sich.

Für int und unsigned int wird der Vergleich als unsigned int durchgeführt. Die Konvertierung ergibt den gleichen Wert und der Vergleich ist richtig. Beachten Sie, dass Sie die Zahlen mit einem geeigneten Format gedruckt werden sollen: printf("si = %i, ui = %u\n", si, ui);

Für den long und unsigned long Test, Ihr Computer scheint 64-Bit-Long-Positionen zu haben, wird der Vergleich als unsigned long ausgeführt, der long Wert wird umgewandelt in ein unsigned long aber hat die gleiche Darstellung, zum Vergleich ist wieder wahr.

Beachten Sie, dass Sie keine Zahlen größer als der Maximalwert in einem signierten Typ speichern soll:

signed short ss = 0x8000; nicht speichern -32768 zu ss garantiert.

Gleiches Problem für signed int si = 0x80000000; und signed long sl = 0x8000000000000000L;.

1

Es scheint, dass in Ihrem Compiler sowohl short als auch unsigned short in int ohne Informationsverlust konvertiert werden können; ihr Vergleich erfolgt nach der Konvertierung ("promotion").

Die aktionen im Abschnitt Usual Arithmetic Conversions bei securecoding.cert.org

  1. erklärt sind, wenn beide Operanden denselben Typ haben, ist keine weitere Umwandlung benötigt.

  2. Wenn beide Operanden des gleichen Typs sind integer (signierte oder nicht signierte ), der Operand mit der Art der geringeren ganzzahligen Umwandlung rank mit Rang größer der Art des Operanden umgewandelt werden.

  3. Wenn der Operanden, die unsigned integer Typen hat hat Rang größer oder gleich den Rang des Typs des anderen Operanden, die Operanden mit vorzeichenbehaftete Ganzzahl-Typ mit den Typ des Operanden umgewandelt wird unsigned ganzzahliger Typ

  4. Wenn der Typ des Operanden mit signierten Integer-Typ alle Werte von der Art des Operanden mit unsigned integer-Typ, der Operand mit unsigned Integer-Typ ist, auf den Typ des Operanden umgewandelt darstellen kann mit signiert Integer-Typ.

  5. Andernfalls werden beide Operanden in unsigned der Integer-Typ umgewandelt auf den Typ des Operanden mit signierten Integer-Typ entspricht.