int oder unsigned int
-
Hallo
Mich würde interessieren ob und wie häufig ihr mit unsigned int arbeitet. In meinem Projekt kommen fast ausschließlich positive Werte vor. Wenn irgenwo ein negativer Wert auftritt ist definitiv was falsch gelaufen. Ist es nun sinnvoll alle int-Deklarationen durch unsigned int zu ersetzen?
Was für Vorteile - außer einem größeren Wertebereich den ich eh nicht ausschöpfe - haben unsignend int?
Wendet man unsignend int auch in for-Schleifen an?for(unsigned int=0;i<100;++i)Danke für eure Antworten
Gruß Zaus
-
Hallo!
Wirkliche Vorteile hast du keine, egal ob int oder unsigned int.
Für eine Aufzählung, die im Regelfall ja immer positiv ist, solltest
du unsigned int oder gleich size_t verwenden (was im Prinzip unsigned int ist).Gruß
Source
-
...
-
Alles klar, vielen Dank euch.
-
Hallo,
der Unterschied macht sich Hauptsächlich bei Shiftoperationen bemerkbar:
#include <stdio.h> int main( void ) { unsigned int ui = 0xFFFFFFFF; int si = 0xFFFFFFFF; ui >>= 1; si >>= 1; printf( "%x %x", ui, si ); }ergibt
7fffffff ffffffff
Für 64-bit-systeme ist die Anzahl der Fs zu erhöhen.
signed integers haben bei Schleifen einen Vorteil, weil man auf >= 0 prüfen kann, was meistens schneller geht:
int array[16]; for( int i=15; i>= 0; i++ ) array[i] = 0;mfg Martin
-
mgaeckler schrieb:
for( int i=15; i>= 0; i++ )Muß natürlich
for( int i=15; i>= 0; i-- ) // ^^sein
-
Ich verwende unsigned int eigentlich hauptsächlich beim Zugreifen auf Vectorelemente (wofür du aber auch einen iterator nehmen kannst), weil sonst beim Überprüfen auf die Vectorgröße der Compiler mich warnt, dass ich unsigned und signed miteinander vergleiche.

-
wxSkip schrieb:
Ich verwende unsigned int eigentlich hauptsächlich beim Zugreifen auf Vectorelemente (wofür du aber auch einen iterator nehmen kannst), weil sonst beim Überprüfen auf die Vectorgröße der Compiler mich warnt, dass ich unsigned und signed miteinander vergleiche.

Da habe ich mir aus dem gleichen Grunde size_t angewöhnt. (Und ein ganz klein wenig, weil size_t von 16 auf 32 Bit schön mitgewachsen ist, aber nur ein klein wenig.)
-
volkard schrieb:
wxSkip schrieb:
Ich verwende unsigned int eigentlich hauptsächlich beim Zugreifen auf Vectorelemente (wofür du aber auch einen iterator nehmen kannst), weil sonst beim Überprüfen auf die Vectorgröße der Compiler mich warnt, dass ich unsigned und signed miteinander vergleiche.

Da habe ich mir aus dem gleichen Grunde size_t angewöhnt.
Stimmt, ich sollte mir auch mal ein bisschen Schreibarbeit sparen.
BTW: Du solltest deine Signatur wieder ändern :p
-
Bei unsigned Variablen ergibt a-b auch wieder unsigned, das kann bei b>a Überraschungen geben, wenn einem gerade nicht klar ist, dass a und b unsigned sind.
Ich verwende unsigned praktisch nur für Zeit und Dateigrößen/offsets, da weiß ich dann schon Bescheid.Was spricht gegen ein globales
typedef unsigned int uint;?
Das habe ich sogar als Keyword eingetragen. Was die C++-Designer versäumt haben, muss man eben selbst nachholen.
-
Athar schrieb:
Was spricht gegen ein globales
typedef unsigned int uint;?Nichts. Jeder kann es flüssig lesen.
-
Zaus schrieb:
Mich würde interessieren ob und wie häufig ihr mit unsigned int arbeitet. In meinem Projekt kommen fast ausschließlich positive Werte vor.
Bei mir auch. Aber ein winziges Pünktchen kann für signe dint sprechen, obwohl im Wertebereich nur unsigned int vorkommen kann. Also erstmal, bei Indexzugriffen und plus und minus ist es gleich schnell. Manchmal kann es helfen, zu wissen, ob man als Programmierfehler einen underflow oder einen overflow erzeugt hat, und man spart ein paar Minuten beim Debuggen.
Klassisches Beispiel ist der op[] bei einem eigenen Arraydouble& operator[](unsigned int index){ assert(index<size); return data[index]; }versus
double& operator[](int index){ assert(index>=0); assert(index<size); return data[index]; }Die beiden decken genau die selben Fehler auf. Nnicht einen mehr! Aber qualifizierter. Beim Sortieralgo, der nicht klappt wegen Indexgrenzenproblemen, ist es für mich höchst interessant, ob index>=0 oder index<size verletzt wurde.
Ist aber nur so ein theoretisches Ding, was ich mal gelesen hatte, aber in der Praxis hat es mir nicht nicht geholfen.
-
Bei mir ist eigentlich immer unsigned. Das Wörtchen "int" findet sich bei mir in 2000 Zeilen Code nirgends.

> Da habe ich mir aus dem gleichen Grunde size_t angewöhnt. (Und ein ganz klein wenig, weil size_t von 16 auf 32 Bit schön mitgewachsen ist, aber nur ein klein wenig.)
Wenn man päpstlicher als der Papst sein will sollte man doch eh std::vector<T>::size_type benutzen.
-
Ad aCTa schrieb:
Wenn man päpstlicher als der Papst sein will sollte man doch eh std::vector<T>::size_type benutzen.
Ja, aber da vertraue ich auf die Vernunft der vector-Bauer. Vielleicht wird mit auto und decltype das besser. Nein, nicht wirklich. range-based for-loops entschärfen noch ein wenig. Ich glaube, ich werde bei size_z bleiben und mich darauf verlassen, daß anycontainer<anytype>::size_type nicht größer als size_t ist. Aus purer Faulheit.
-
Zaus schrieb:
Was für Vorteile - außer einem größeren Wertebereich den ich eh nicht ausschöpfe - haben unsignend int?
Dass man nen Rage-Check mit nur
v <= maxmachen kann, falls die untere Grenze 0 ist - was halt relativ oft vorkommt.Und dass man keine Probleme mit signed vs. unsigned bei Vergleichen mit diversen size_t bekommen kann. Und einfach überall signed Typen zu verwenden, ist in C++ auch mühsam, da die Standard-Library gerne überall unsigned Typen verwendet. Und dauernd rumcasten nervt auch.
-
volkard schrieb:
Ad aCTa schrieb:
Wenn man päpstlicher als der Papst sein will sollte man doch eh std::vector<T>::size_type benutzen.
Ja, aber da vertraue ich auf die Vernunft der vector-Bauer. Vielleicht wird mit auto und decltype das besser. Nein, nicht wirklich. range-based for-loops entschärfen noch ein wenig. Ich glaube, ich werde bei size_z bleiben und mich darauf verlassen, daß anycontainer<anytype>::size_type nicht größer als size_t ist. Aus purer Faulheit.
Ist iirc vom Standard ohnehin garantiert.
-
Die grundlegende Idee für vorzeichenlose Integer-Typen scheint ursprünglich mal gewesen zu sein, den benutzbaren Wertebereich nach oben zu erweitern; nur so kann ich mir die Promotionsvorschriften erklären. Nimm beispielsweise
#include <iostream> int main() { std::cout << 0 - 2u << std::endl; } // Ausgabe (bei mir): // // 4294967294Um solche Verwirrungen und exzessives Gecaste zu vermeiden, benutze ich prinzipiell vorzeichenbehaftete Typen, sofern keine guten Gründe dagegen sprechen (wie etwa einfachere Range-Prüfung im []-Operator). Gerade, wenn man mit der Variable nachher noch rechnen will, ist allein der Umstand, dass sie keine negativen Werte annehmen wird, meiner Meinung nach nicht ausreichend. Konkretes Beispiel:
unsigned long julian_day(unsigned y, unsigned m, unsigned d) { // berechne julianisches Datum } // ... // Tage zwischen zwei Daten. // Fliegt aber auseinander, wenn Datum 1 nach Datum 2 liegt. int date_diff = julian_day(y2, m2, d2) - julian_day(y1, m1, d1);Hier wäre long julian_day(...) natürlicher zu benutzen.
-
Es gibt Anwendungsfälle, z.B. in der Bildverarbeitung, wo unsigned durchaus Sinn macht. Ein Pixel wird typischerweise als unsigned char definiert (im Fall eines 8bit Grauwertbildes).
Bei einer Filterung des Bildes kann nun Vorzeichenrichtig auf int erweitert werden.
-
seldon schrieb:
unsigned long julian_day(unsigned y, unsigned m, unsigned d) { // berechne julianisches Datum } // ... // Tage zwischen zwei Daten. // Fliegt aber auseinander, wenn Datum 1 nach Datum 2 liegt. int date_diff = julian_day(y2, m2, d2) - julian_day(y1, m1, d1);Hier wäre long julian_day(...) natürlicher zu benutzen.
Naja, das Ergebnis deiner Rechnung ist zwar "implementation defined", aber die Implementation die da nicht auf das richtige Ergebnis kommt, möchte ich sehen
.Wobei ich dir aber schon zustimme, dass sich für Datumsangaben ein unsigned Typ nicht eignet, jedoch aus einem anderen Grund: Man müsste festlegen wann die Zeit angefangen hat. Und damit meine ich nicht 1970 oder 1900, sondern den Urknall, denn Daten vor diesem Nullpunkt können ja nicht existieren.
Für andere Sachen wo es einen natürlichen Nullpunkt gibt der nicht unterschritten werden kann, eignen sich unsigned Typen aber wohl und ich versuche dies wenn möglich auch zu beachten. Es bringt mir zwar keinen Vorteil, aber ich würde mich unwohl fühlen den falschen Typ zu benutzen. Ich benutze auch "size_t" und "ptrdiff_t" nur dann wenn es sich tatsächlich um Bytegrößen oder Pointerdifferenzen handelt und nicht als Synonyme für unsigned int bzw. int. Und auch zurecht, denn bei meiner Implementierung sind diese vom Typ (unsigned) long.
-
Dann nimm meinetwegen
double tropical_years = (julian_day(y2, m2, d2) - julian_day(y1, m1, d1)) / 365.2425;Der Punkt ist, dass man bei Berechnungen auftretende Zwischenergebnisse auch berücksichtigen muss.
Anwendungsabhängig mag ein Jahr noch negativ werden können (obwohl ich von der Behandlung vorgregorianischer Zustände absehen würde, wenn es um zeitgenössische Zusammenhänge geht), aber das julianische Datum ist es per Konvention nicht. Will man weiter als ins Jahr -4712 zurückgehen, muss man zu anderen Mitteln greifen. Auch nehmen Monat und Tag eines Datums nie negative Werte an, es ist aber beim Rechnen mit ihnen durchaus praktisch, ein Vorzeichen zur Verfügung zu haben. Wenn du ein Sparbuch hast - da werden die Zinsen nach wie vor mit der 30/360-Methode berechnet:
int zinstage = (y2 - y1) * 360 + (m2 - m1) * 30 + (d2 - d1);jetzt stell dir mal vor, wie viel hübscher das wäre, wenn die alle von Hand ge-static_cast<int>-et werden müssten.
Es gibt natürlich Zusammenhänge, in denen die Darstellung negativer Zahlen absolut unerwünscht ist, und da macht unsigned dann auch Sinn (fällt unter o.g. "gute Gründe"), und mit Sicherheit ist die Nutzung zweckgebundener typedefs eine sehr, sehr gute Idee (zumal man dann auch leicht ein Vorzeichen einführen oder abschaffen kann, wenn dieses notwendig oder überflüssig werden sollte). Ich meine nur: im Zweifel für das Vorzeichen. Will sagen, wenn keine guten Gründe dagegen sprechen, sollte man ein Vorzeichen ruhig zulassen - sonst kriegt man leicht unerwartete Nebeneffekte, wenn man mit einem vorzeichenbehafteten Typ in Berührung kommt.