Verwenden die meisten Anwendungsentwickler vorzeichenbehaftete Ganzzahlen an Stellen, an denen sie wirklich vorzeichenlose Ganzzahlen verwenden möchten? Ich mache es die ganze Zeit, meine Kollegen auch. Ich habe nicht viele andere umfangreiche Codebasen gesehen (außer der Delphi VCL) und Beispiele im Internet verwenden normalerweise Ganzzahlen. Während die VCL-Entwickler ihre eigenen Datentypen verwenden (was der nicht faulste Weg wäre, Variablen zu deklarieren).
Etwas an diesem Code scheint etwas schrecklich zu sein
TStuffRec = record
recordID : Integer;
thingID : Integer;
otherThingID : Integer;
end;
wenn es geschrieben werden könnte als
TStuffRec = record
recordID : Cardinal;
thingID : Cardinal;
otherThingID : Cardinal;
end;
Funktionell funktionieren diese Datensätze fast immer gleich (und funktionieren hoffentlich auch in 64-Bit-Delphi weiterhin gleich). Bei sehr großen Zahlen treten jedoch Konvertierungsprobleme auf.
Die Verwendung von Ints ohne Vorzeichen hat jedoch auch Nachteile. Hauptsächlich weil es ärgerlich ist, beides zu mischen.
Die eigentliche Frage ist, ob dies tatsächlich über Best Practices nachgedacht oder in diese aufgenommen wird. Ist es normalerweise nur Sache des Entwicklers?
quelle
Antworten:
Ein Grund, warum ich in Delphi nicht allzu oft vorzeichenlose Ganzzahltypen verwende, ist, dass sie Probleme verursachen können, wenn sie mit vorzeichenbehafteten Ganzzahlen gemischt werden. Hier ist eine, die mich einmal gebissen hat:
Ich hatte
i
als vorzeichenlose Ganzzahl deklariert (schließlich ist es ein Index in einer Liste, die bei 0 beginnt, es muss nie negativ sein, oder?), Aber wennList.Count
0 war, würde es die Schleife nicht wie erwartet kurzschließen, weil0 - 1
bewertet zu einer wirklich hohen positiven Zahl. Hoppla!Zwischen den potenziellen Sicherheitsproblemen beim Mischen von vorzeichenbehafteten und vorzeichenlosen Ganzzahlen und den Bereichsproblemen (wenn Sie positive Zahlen benötigen, die größer als sind
high(signed whatever)
, ist es sehr wahrscheinlich, dass Sie auch positive Zahlen benötigen, die größer alshigh(unsigned whatever)
sind, also bewegen Sie sich Bis zur nächstgrößeren Größe, anstatt von vorzeichenbehafteten zu vorzeichenlosen Größen derselben Größe zu wechseln, ist normalerweise die richtige Aktion.) Ich habe wirklich nicht zu viele Verwendungsmöglichkeiten für vorzeichenlose Ganzzahlen gefunden, wenn ich die meisten Daten darstelle.quelle
Um ehrlich zu sein, neige ich dazu, Ganzzahlen aus Gewohnheit zu verwenden. Ich habe mich daran gewöhnt, dass sie Bereiche bieten, die für die meisten Situationen groß genug sind und negative Werte (wie -1) zulassen. In der Tat wäre die Verwendung von Bytes / Wörtern / Abkürzungen häufig angemessener. Wenn ich jetzt darüber nachdenke, kann ich mich auf folgende Punkte konzentrieren:
Perspektive. Die Tilemap-Größe ist auf 192 x 192 Kacheln begrenzt, daher kann ich Byte zum Adressieren von Kacheln und Schleifen verwenden. Aber wenn die Kartengröße erhöht werden soll, muss ich jede Verwendung durchgehen und sie durch zB ein Wort ersetzen. Wenn ich Off-Map-Objekte zulassen muss, muss ich erneut zu smallint wechseln.
Schleifen. Es ist oft so, dass ich eine Schleife "von i: = 0 bis Count-1" schreibe. Was passiert, wenn "i" Byte ist und Count = 0 ist, dass diese Schleife von 0 bis 255 läuft. Nicht, dass ich es möchte.
Uniformierung. Es ist einfacher, sich "var i: integer" zu merken und anzuwenden. als in jedem Fall anzuhalten und zu denken "Hm .. hier haben wir es mit 0..120 Bereich zu tun .. Byte .. nein, warte, wir brauchen möglicherweise -1 für nicht initialisierte .. Abkürzung .. warte .. was ist, wenn 128 ist nicht genug .. Arrgh! " oder "Warum ist es an diesem Ort klein, keine Abkürzung?"
Kombinieren. Wenn ich zwei oder mehr Klassen miteinander kombinieren muss, verwenden sie möglicherweise unterschiedliche Datentypen für ihre Zwecke. Durch die Verwendung breiterer Typen können unnötige Konvertierungen übersprungen werden.
-1. Selbst wenn die Werte im Bereich 0..n-1 liegen, muss ich häufig den Wert "kein Wert / unbekannt / nicht initialisiert / leer" einstellen, was nach gängiger Praxis -1 ist.
Durch die Verwendung von Ganzzahlen können Sie all diese Probleme überspringen, die Optimierung auf niedriger Ebene vergessen, wenn sie nicht benötigt wird, auf eine höhere Ebene wechseln und sich auf realere Probleme konzentrieren.
PS Wann verwende ich andere Typen?
quelle
Am besten verwenden Sie einen Datentyp, der den Anforderungen der verwendeten Daten entspricht (erwartete Daten).
C # -Beispiele: Wenn ich nur 0 bis 255 unterstützen müsste, würde ich ein Byte verwenden.
Wenn ich 1.000.000 negative und positive unterstützen musste, dann int.
Größer als 4,2 Milliarden, dann verwenden Sie eine lange.
Durch Auswahl des richtigen Typs verwendet das Programm die optimale Speichermenge, und verschiedene Typen verwenden unterschiedliche Speichermengen.
Hier ist eine C # int-Referenz von MSDN.
quelle
Integer
beträgt der Datentyp auf einem 32-Bit-Computer 32 Bit und auf einem 64-Bit-Computer anscheinend 64 Bit.int
ist nur eine Abkürzung fürSystem.Int32
, egal auf welcher Maschine der Code ausgeführt wird.type int System.Int32
oder so? Könnte es in einer zukünftigen Version des Frameworks so einfach geändert werden?uint
ist einer dieser nicht konformen Typen, was bedeutet, dass er nicht in öffentlich zugänglichen APIs verwendet werden sollte, um zu vermeiden, dass die Verwendung dieser API in anderen .NET-Sprachen als der, in der die Bibliothek geschrieben ist, beeinträchtigt wird. Aus diesem Grund auch das .NET-Framework API selbst verwendetint
wouint
würde tun.Ganzzahlige Typen ohne Vorzeichen sollten nur zur Darstellung von Kardinalzahlen in Sprachen verwendet werden, in denen sie Kardinalzahlen darstellen. Aufgrund der Funktionsweise der Computer, auf denen C ausgeführt wurde, verhielten sich vorzeichenlose Ganzzahltypen wie Mitglieder von algebraischen Mod-2 ^ n-Ringen (was bedeutet, dass überlaufende Berechnungen vorhersehbar "umbrechen" würden), und die Sprache gibt an, dass dies in vielen Fällen der Fall ist erforderlich, um sich als abstrakte algebraische Ringe zu verhalten, selbst wenn ein solches Verhalten nicht mit dem Verhalten von Kardinalzahlen oder mathematischen ganzen Zahlen vereinbar wäre.
Wenn eine Plattform separate Typen für Kardinalzahlen und algebraische Ringe vollständig unterstützt, würde ich vorschlagen, dass Kardinalzahlen mit Kardinalzahlentypen verarbeitet werden (und Dinge, die mit den Ringtypen umbrochen werden müssen). Solche Typen könnten nicht nur Zahlen speichern, die doppelt so groß sind wie signierte Typen, sondern eine Methode, die einen Parameter eines solchen Typs empfängt, müsste nicht prüfen, ob er negativ ist.
Angesichts des relativen Fehlens von Kardinalzahlentypen ist es jedoch im Allgemeinen am besten, einfach Ganzzahlen zu verwenden, um sowohl mathematische Ganzzahlen als auch Kardinalzahlen darzustellen.
quelle