Der wirkliche Unterschied zwischen “int” und “unsigned int”

Lesezeit: 5 Minuten

Benutzeravatar von Fabricio
Fabricio

int:

Der 32-Bit-Datentyp int kann ganzzahlige Werte im Bereich von –2.147.483.648 bis 2.147.483.647 enthalten. Sie können diesen Datentyp auch als signed int oder signed bezeichnen.

unsigned int :

Der 32-Bit unsigned int Datentyp kann ganzzahlige Werte im Bereich von 0 bis 4.294.967.295 enthalten. Sie können diesen Datentyp auch einfach als unsigned bezeichnen.

Ok, aber in der Praxis:

int x = 0xFFFFFFFF;
unsigned int y = 0xFFFFFFFF;
printf("%d, %d, %u, %u", x, y, x, y);
// -1, -1, 4294967295, 4294967295

Kein Unterschied, Oo, ich bin etwas verwirrt.

  • Sie müssen an die denken binär Darstellung von sowohl ein int und ein unsigned int.

    – Oded

    28. Januar 2012 um 13:08 Uhr

  • Der wahre Grund, warum dies passieren kann, ist, dass C a ist schwach getippt Sprache. Aber unsigned int und int sind wirklich anders.

    – cha0site

    28. Januar 2012 um 13:13 Uhr

  • stackoverflow.com/questions/247873/…

    – Rafal Rawicki

    28. Januar 2012 um 13:18 Uhr

  • mögliches Duplikat von warum unsigned int 0xFFFFFFFF gleich int -1 ist?

    – Rafal Rawicki

    28. Januar 2012 um 13:18 Uhr

Hehe. Sie haben hier eine implizite Besetzung, weil Sie erzählen printf welchen Typ zu erwarten.

Probieren Sie dies stattdessen für die Größe aus:

unsigned int x = 0xFFFFFFFF;
int y = 0xFFFFFFFF;

if (x < 0)
    printf("one\n");
else
    printf("two\n");
if (y < 0)
    printf("three\n");
else
    printf("four\n");

Benutzeravatar von cnicutar
Cnicutar

Ja, denn in Ihrem Fall verwenden sie die gleiche Darstellung.

Das Bitmuster 0xFFFFFFFF sieht zufällig wie -1 aus, wenn es als 32b-Ganzzahl mit Vorzeichen interpretiert wird, und wie 4294967295, wenn es als 32b-Ganzzahl ohne Vorzeichen interpretiert wird.

Es ist dasselbe wie char c = 65. Wenn Sie es als Ganzzahl mit Vorzeichen interpretieren, ist es 65. Wenn Sie es als Zeichen interpretieren, ist es a.


Wie R und pmg betonen, ist es technisch gesehen ein undefiniertes Verhalten, Argumente zu übergeben, die nicht mit den Formatbezeichnern übereinstimmen. Das Programm konnte also alles tun (vom Drucken zufälliger Werte bis zum Absturz, bis zum Drucken des “Richtigen” usw.).

Darauf weist die Norm hin 7.19.6.1-9

Wenn eine Konvertierungsspezifikation ungültig ist, ist das Verhalten undefiniert. Wenn eines der Argumente nicht der richtige Typ ist für die entsprechende Konvertierungsspezifikation ist das Verhalten undefiniert.

  • Der wahre Grund ist, dass er %u benutzt, um beides zu drucken.

    – Shadyabhi

    28. Januar 2012 um 13:11 Uhr

  • Der wahre Grund ist, dass er aufgerufenes undefiniertes Verhalten durch Übergeben einer nicht typübereinstimmenden Formatzeichenfolge an printf. Ich möchte fast alle Antworten ablehnen, die dies überspringen und auf irrelevante Dinge über die Darstellung hinweisen …

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    28. Januar 2012 um 13:33 Uhr


  • @R .. Das ist richtig, das Nichtübereinstimmen des Formats und der Argumente ist ein undefiniertes Verhalten. Fühlen Sie sich frei, abzustimmen, ich habe nichts dagegen 🙂

    – Cnicutar

    28. Januar 2012 um 13:33 Uhr


  • @R..: Du bist falsch, dies ist kein undefiniertes Verhalten. Siehe C99 Abschnitt 6.5.2.2 Absatz 6.

    – cha0site

    28. Januar 2012 um 13:49 Uhr

  • Die Dokumentation von fprintf ist sehr explizit: “Wenn ein Argument nicht den richtigen Typ für die entsprechende Konvertierungsspezifikation hat, ist das Verhalten undefiniert.”

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    28. Januar 2012 um 22:05 Uhr

Es gibt keinen Unterschied zwischen den beiden darin, wie sie im Speicher und in Registern gespeichert werden, es gibt keine vorzeichenbehaftete und vorzeichenlose Version von int-Registern, es werden keine vorzeichenbehafteten Informationen mit int gespeichert, der Unterschied wird nur relevant, wenn Sie mathematische Operationen durchführen, gibt es signierte und unsignierte Version der in die CPU integrierten mathematischen Operationen und die Signiertheit teilen dem Compiler mit, welche Version verwendet werden soll.

  • Diese Antwort ist die einfachste

    – Thanh-Nhon Nguyen

    17. Juni 2016 um 20:37 Uhr

Das Problem ist, dass Sie aufgerufen haben Undefiniertes Verhalten.


Wenn Sie aufrufen UB Alles kann passieren.

Die Zuordnungen sind ok; in der ersten Zeile findet eine implizite Konvertierung statt

int x = 0xFFFFFFFF;
unsigned int y = 0xFFFFFFFF;

Allerdings ist der Aufruf an printfist nicht in Ordnung

printf("%d, %d, %u, %u", x, y, x, y);

es ist UB nicht übereinstimmen % Bezeichner und den Typ des Arguments.
In Ihrem Fall geben Sie 2 an ints und 2 unsigned ints in dieser Reihenfolge durch Bereitstellung 1 int1 unsigned int1 intund 1 unsigned int.


Nicht tun UB!

Benutzeravatar von Rafał Rawicki
Rafal Rawicki

Die interne Darstellung von int und unsigned int ist dasselbe.

Wenn Sie daher denselben Formatstring an übergeben printf es wird genauso gedruckt.

Allerdings gibt es Unterschiede, wenn man sie vergleicht. In Betracht ziehen:

int x = 0x7FFFFFFF;
int y = 0xFFFFFFFF;
x < y // false
x > y // true
(unsigned int) x < (unsigned int y) // true
(unsigned int) x > (unsigned int y) // false

Dies kann auch ein Vorbehalt sein, da beim Vergleichen von vorzeichenbehafteten und vorzeichenlosen Ganzzahlen eine davon implizit so umgewandelt wird, dass sie mit den Typen übereinstimmt.

Benutzeravatar von AlexT
AlexT

Er fragt nach der real Unterschied. Wenn Sie über undefiniertes Verhalten sprechen, befinden Sie sich auf der Garantieebene der Sprachspezifikation – das ist weit von der Realität entfernt. Um den wirklichen Unterschied zu verstehen, überprüfen Sie bitte dieses Snippet (natürlich ist dies UB, aber es ist perfekt auf Ihrem Lieblingscompiler definiert):

#include <stdio.h>

int main()
{
    int i1 = ~0;
    int i2 = i1 >> 1;
    unsigned u1 = ~0;
    unsigned u2 = u1 >> 1;
    printf("int         : %X -> %X\n", i1, i2);
    printf("unsigned int: %X -> %X\n", u1, u2);
}

Die binäre Darstellung ist der Schlüssel. Ein Beispiel: Unsigned int in HEX

 0XFFFFFFF = translates to = 1111 1111 1111 1111 1111 1111 1111 1111 

Was darstellt 4,294,967,295 in einer positiven Zahl zur Basis zehn. Aber wir brauchen auch eine Möglichkeit, negative Zahlen darzustellen. Also entschieden sich die Gehirne für das Zweierkomplement. Kurz gesagt, sie nahmen das Bit ganz links und entschieden, dass die Zahl negativ sein wird, wenn es eine 1 ist (gefolgt von mindestens einem anderen Bit, das auf 1 gesetzt ist). Und das Bit ganz links ist auf 0 gesetzt, die Zahl ist positiv. Schauen wir uns nun an, was passiert

0000 0000 0000 0000 0000 0000 0000 0011 = 3

Hinzufügen zu der Zahl, die wir schließlich erreichen.

0111 1111 1111 1111 1111 1111 1111 1111 = 2,147,483,645

die höchste positive Zahl mit einer vorzeichenbehafteten Ganzzahl. Lassen Sie uns 1 weiteres Bit hinzufügen (die binäre Addition trägt den Überlauf nach links, in diesem Fall werden alle Bits auf eins gesetzt, sodass wir auf dem Bit ganz links landen)

1111 1111 1111 1111 1111 1111 1111 1111 = -1

Ich denke also, wir könnten kurz sagen, dass der Unterschied darin besteht, dass der eine negative Zahlen zulässt, der andere nicht. Wegen dem Zeichenbit oder Bit ganz links oder höchstwertiges Bit.

1416850cookie-checkDer wirkliche Unterschied zwischen “int” und “unsigned int”

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy