C/C++-Verwendung von int oder unsigned int

Lesezeit: 9 Minuten

Benutzer-Avatar von developerbmw
Entwicklerbmw

In vielen Codebeispielen, Quellcode, Bibliotheken usw. sehe ich die Verwendung von int, wenn, soweit ich sehen kann, an unsigned int würde viel mehr Sinn machen.

Ein Ort, an dem ich das oft sehe, ist in for Schleifen. Siehe folgendes Beispiel:

for(int i = 0; i < length; i++)
{
    // Do Stuff
}

Warum um alles in der Welt würdest du ein verwenden int eher als ein unsigned int? Ist es nur Faulheit – die Leute haben keine Lust aufs Tippen unsigned?

  • Es ist tatsächlich sicherer zu verwenden int wenn length kann negativ sein. Wenn du benutzt unsigned intdann length wird umgewandelt in unsigned int zu. -1 wird so etwas wie 4294967295, und schlimme Dinge passieren.

    – Brian Bi

    23. März 2014 um 5:34 Uhr

  • Ich stimme zu, aber wann haben Sie eine negative Länge? Ich spreche eher von Fällen, in denen keine Negative involviert sind – wie oben.

    – Entwicklerbmw

    23. März 2014 um 5:37 Uhr

  • Wenn length ist viel kleiner als INT_MAX dann ist es gleichbedeutend mit verwenden int und unsigned int . Ich gehe mit dem, der weniger tippt 🙂

    – MM

    23. März 2014 um 5:50 Uhr

  • wenn length ist von int Geben Sie ein, warum Sie verwenden müssen unsigned?

    – Die Maske

    23. März 2014 um 5:51 Uhr

  • Auf der Maschinenebene arbeiten vorzeichenbehaftete und vorzeichenlose Ganzzahlen mit genau derselben Logik. Es sei denn, Ihr Wert von i auf den Maximalwert geht (was sehr unwahrscheinlich ist, wenn i ist ein Array-Index und i 32-Bit oder größer ist), spielt es keine Rolle, ob Sie signiert oder unsigniert verwenden. Das nur Grund unsigned vorhanden ist, wenn Sie tatsächlich das höchstwertige Bit benötigen, um Ihren positiven Bereich um einen weiteren Faktor von 2 zu erweitern, aber nicht mehr.

    – Mark Lakata

    23. März 2014 um 5:52 Uhr

Verwenden unsigned kann zu Programmierfehlern führen, die schwer zu erkennen sind, und es ist normalerweise besser, signiert zu verwenden int nur um sie zu vermeiden. Ein Beispiel wäre, wenn Sie sich entscheiden, rückwärts statt vorwärts zu iterieren und Folgendes schreiben:

for (unsigned i = 5; i >= 0; i--) {
    printf("%d\n", i);
}

Ein anderer wäre, wenn Sie innerhalb der Schleife etwas rechnen:

for (unsigned i = 0; i < 10; i++) {
    for (unsigned j = 0; j < 10; j++) {
        if (i - j >= 4) printf("%d %d\n", i, j);
    }
}

Verwenden unsigned führt das Potenzial für diese Art von Fehlern ein, und es gibt nicht wirklich einen Vorteil.

  • Es ist ein ganzes Jahrzehnt her, dass i >= 0 vom Compiler als Warnung gemeldet wird, wenn ein unsigned int als Typ für i verwendet wird. Auch wenn die ‘5’ nach Ihrem Beispiel als Größe eines Arrays kommt, ist sie normalerweise vom Typ size_t (ohne Vorzeichen), und um keine Warnung (oder Umwandlung) zu haben, kann es sich um einen vorzeichenlosen Int und eine Vorwärtsschleife handeln erforderlich.

    – Stefano Buora

    12. Juli 2017 um 19:37 Uhr

  • In meinen Augen sind dies nur einige Beispiele dafür, wie die Leute jetzt wissen, wie es geht korrekt Verwenden Sie die von ihnen gewählten Tools (oder für eine schlechte Wahl selbst) … Beide Beispiele sind nicht die Schuld von unsigned int, sondern des Programmierers wollen produzieren Negativ Werte mit einem Tool, das dies nicht kann. Versuchen Sie, eine Mutter mit einem Schraubendreher festzuziehen, Sie werden wahrscheinlich scheitern. Trotzdem ist ein Schraubendreher ein nützliches Werkzeug – oder würden Sie das bestreiten?

    – Aconcagua

    20. November 2018 um 7:56 Uhr

  • @StefanoBuora Tatsächlich gibt es Möglichkeiten, mit unsigned int auch in Rückwärtsschleifen korrekt umzugehen: for(unsigned int i = start + 1; i-- > 0; ) oder for(unsigned int i = start; i <= start; --i) – letztere explizit vom Unterlauf profitieren.

    – Aconcagua

    20. November 2018 um 7:57 Uhr

Es ist im Allgemeinen Faulheit oder Unverständnis.

Ich verwende immer unsigned int, wenn der Wert nicht negativ sein soll. Dies dient auch dem Dokumentationszweck, um anzugeben, was die richtigen Werte sein sollten.

IMHO ist die Behauptung, dass es sicherer ist, “int” als “unsigned int” zu verwenden, einfach falsch und eine schlechte Programmierpraxis.

Wenn Sie Ada oder Pascal verwendet haben, sind Sie an die noch sicherere Praxis gewöhnt, bestimmte Bereiche für Werte anzugeben (z. B. eine ganze Zahl, die nur 1, 2, 3, 4, 5 sein kann).

  • Ich finde einige der Antworten hier besorgniserregend. Die Verwendung von int ist beängstigend, da dies einen Programmierfehler vertuscht.

    – Benutzer3344003

    25. März 2014 um 5:17 Uhr

  • Die “Programmierfehler” in den anderen Antworten sind nur Programmierfehler, wenn Sie vorzeichenlose Ganzzahlen verwenden, und absolut sinnvoller Code, wenn Sie vorzeichenbehaftete Ganzzahlen verwenden.

    – Nemetroid

    7. Mai 2018 um 16:12 Uhr

  • @nemetroid Die Programmierfehler sind nur Fehler, weil der Programmierer das schlechte Werkzeug für die beabsichtigte Aufgabe ausgewählt oder es nicht richtig verwendet hat. Es ist nicht die Schuld von unsigned int.

    – Aconcagua

    20. November 2018 um 7:55 Uhr

  • @Aconcagua: Es ist eine Binsenweisheit, dass Fehler auf falsch geschriebenen Code zurückzuführen sind. Sie könnten dasselbe Argument für goto- oder null-Zeiger oder andere fehleranfällige Programmierkonstrukte/-tools anführen.

    – Nemetroid

    21. November 2018 um 10:25 Uhr

Wenn length ist auch int, dann sollten Sie denselben Integer-Typ verwenden, da sonst seltsame Dinge passieren, wenn Sie signierte und unsignierte Typen in einer Vergleichsanweisung mischen. Die meisten Compiler werden Sie warnen.

Man könnte weiter fragen, warum sollte length unterschrieben werden? Nun, das ist wahrscheinlich historisch.

Auch wenn Sie sich entscheiden, die Schleife umzukehren, dh

for(int i=length-1;i>=0 ;i--)
{
   // do stuff
}

Die Logik bricht, wenn Sie unsigned ints verwenden.

  • Sie können die Schleife auch mit unsigned int umkehren: for (unsigned int i = length; i--; )

    – MM

    23. März 2014 um 5:50 Uhr

  • @MattMcNabb – du hast Recht! huh, viele, viele Jahre Programmieren und ich habe dieses Muster noch nie gesehen (wo die for bedingt hat eine Nebenwirkung). Jeden Tag etwas Neues lernen.

    – Mark Lakata

    23. März 2014 um 5:56 Uhr

  • Natürlich Du kann Schreiben Sie eine Umkehrschleife mit unsigned ints. Der Punkt ist (zumindest nahm ich an), dass das Schreiben der Schleife viel einfacher falsch zu machen ist, wenn Sie unsigned verwenden.

    – Benjamin Lindley

    23. März 2014 um 5:59 Uhr


  • Nicht seltsame Dinge aber ganzheitliche Förderung.

    – Ben Jackson

    23. März 2014 um 6:10 Uhr

  • @MarkLakata Ein weiteres Muster, das Ihnen gefallen könnte: for(unsigned int i = length - 1; i < length; --i) (Ich persönlich bevorzuge das eine nicht gegenüber dem anderen, nur der Vollständigkeit halber).

    – Aconcagua

    20. November 2018 um 7:58 Uhr


Benutzeravatar von sherrelbc
sherrelbc

Ich habe mich entschieden, beim Programmieren so explizit wie möglich zu sein. Das heißt, wenn ich beabsichtige, eine Variable zu verwenden, deren Wert immer positiv ist, dann unsigned wird genutzt. Viele hier erwähnen “schwer zu erkennende Fehler”, aber nur wenige geben Beispiele. Betrachten Sie das folgende Advocate-Beispiel für die Verwendung unsignedim Gegensatz zu den meisten Beiträgen hier:

enum num_things {
    THINGA = 0,
    THINGB,
    THINGC,
    NUM_THINGS
};

int unsafe_function(int thing_ID){
    if(thing_ID >= NUM_THINGS)
        return -1;

    ...
}

int safe_function(unsigned int thing_ID){
    if(thing_ID >= NUM_THINGS)
        return -1;

    ...
}

int other_safe_function(int thing_ID){
    if((thing_ID >=0 ) && (thing_ID >= NUM_THINGS))
        return -1;

    ...
}

/* Error not caught */
unsafe_function(-1);

/* Error is caught */
safe_function((unsigned int)-1);

Was passiert im obigen Beispiel, wenn ein negativer Wert als übergeben wird? thing_ID? Im ersten Fall werden Sie feststellen, dass der negative Wert dies nicht ist größer als oder gleich wie NUM_THINGSsodass die Funktion weiterhin ausgeführt wird.

Im zweiten Fall fangen Sie dies tatsächlich zur Laufzeit ab, da die Vorzeichen von thing_ID zwingt die Bedingung, eine auszuführen vorzeichenloser Vergleich.

Natürlich Du könnte mach sowas other_safe_functionaber dies scheint eher ein Kniff zu sein, vorzeichenbehaftete Ganzzahlen zu verwenden, als expliziter zu sein und zunächst unsigned zu verwenden.

Benutzeravatar von Khoi Pham
Khoi Pham

Ich denke, der wichtigste Grund ist, ob Sie sich entscheiden unsigned int, können einige logische Fehler auftreten. In der Tat benötigen Sie oft nicht die Reichweite von unsigned intverwenden int ist sicherer.

  • Ich stimme dir nicht zu. Bei richtiger Anwendung sollten keine “logischen Fehler” auftreten. Wenn ich programmiere, bin ich gerne explizit, anstatt die sichere Option zu verwenden, die später möglicherweise unbeabsichtigte Folgen haben könnte (z. B. einen Überlauf).

    – Entwicklerbmw

    23. März 2014 um 5:41 Uhr


  • @Brett: Das Hinzufügen eines zusätzlichen Bits trägt nicht viel dazu bei, die Möglichkeit eines Überlaufs einzudämmen. Wenn Sie es mit Zahlen zu tun haben, die groß genug sind, wo ein Überlauf möglich ist, dann sollten Sie einen größeren Integer-Typ verwenden, so dass der Überlauf ist nicht eine Möglichkeit, bei Bedarf auf einen unbegrenzten Integer-Typ zurückzugreifen.

    – Benjamin Lindley

    23. März 2014 um 5:44 Uhr


  • Es gibt Situationen, in denen der Überlauf gleichmäßig ist gewünscht, zB ein Zeitzähler auf einem Mikrocontroller. Was sollte sonst passieren, wenn die MCU lange genug läuft, um den Bereich des Zählers zu überschreiten? Signed Integer würde bei Überlauf negative Werte erzeugen – abgesehen davon ist dies eigentlich bis C++20 undefiniertes Verhalten!

    – Aconcagua

    20. November 2018 um 7:50 Uhr

Benutzeravatar von LiorA
LiorA

Dieser winzige Code ist anwendungsfallbezogen. Wenn Sie ein Vektorelement aufrufen, ist der Prototyp int, aber es gibt viele moderne Möglichkeiten, dies in C ++ zu tun, z. for(const auto &v : vec) {} oder Iteratoren, in einigen Berechnungen, wenn es kein Subtrahieren/Erreichen einer negativen Zahl gibt, können und sollten Sie unsigned verwenden (erklärt den erwarteten Wertebereich besser), manchmal zeigen Ihnen so viele hier gepostete Beispiele tatsächlich brauchen int, aber die Wahrheit ist, dass es nur um Anwendungsfälle und Situationen geht, keine strenge Regel gilt für alle Anwendungsfälle und es wäre irgendwie dumm, eine zu erzwingen …

  • Ich stimme dir nicht zu. Bei richtiger Anwendung sollten keine “logischen Fehler” auftreten. Wenn ich programmiere, bin ich gerne explizit, anstatt die sichere Option zu verwenden, die später möglicherweise unbeabsichtigte Folgen haben könnte (z. B. einen Überlauf).

    – Entwicklerbmw

    23. März 2014 um 5:41 Uhr


  • @Brett: Das Hinzufügen eines zusätzlichen Bits trägt nicht viel dazu bei, die Möglichkeit eines Überlaufs einzudämmen. Wenn Sie es mit Zahlen zu tun haben, die groß genug sind, wo ein Überlauf möglich ist, dann sollten Sie einen größeren Integer-Typ verwenden, so dass der Überlauf ist nicht eine Möglichkeit, bei Bedarf auf einen unbegrenzten Integer-Typ zurückzugreifen.

    – Benjamin Lindley

    23. März 2014 um 5:44 Uhr


  • Es gibt Situationen, in denen der Überlauf gleichmäßig ist gewünscht, zB ein Zeitzähler auf einem Mikrocontroller. Was sollte sonst passieren, wenn die MCU lange genug läuft, um den Bereich des Zählers zu überschreiten? Signed Integer würde bei Überlauf negative Werte erzeugen – abgesehen davon ist dies eigentlich bis C++20 undefiniertes Verhalten!

    – Aconcagua

    20. November 2018 um 7:50 Uhr

1396950cookie-checkC/C++-Verwendung von int oder unsigned int

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

Privacy policy