Guten Abend,
ich hab eine allgemeine Funktion geschrieben, die einen uint32_t-Wert
zurück gibt. Es kann jedoch auch vorkommen, dass es sich um eine
negative (also einen signed Wert) Zahl handelt. Meine Frage ist nun, ob
das ganze einfach durch einen expliziten Typecast gelöst werden kann?
Z.B. so:
Das Verhalten vorzeichenbehafteter Typen bei Überlauf ist offiziell
undefiniert. Du wirst sehr wahrscheinlich einfach bloss die unteren 16
Bits kriegen, mit und ohne Cast.
Der Cast wird dir ggf. eine aggressiv eingestellte Warnung ersparen,
aber typischerweise nichts am erhaltenen Wert ändern. Eine Sättigung zu
grosser oder kleiner Werte auf die Limits erfolgt nicht.
Max M. schrieb:> Guten Abend,>> ich hab eine allgemeine Funktion geschrieben, die einen uint32_t-Wert> zurück gibt. Es kann jedoch auch vorkommen, dass es sich um eine> negative (also einen signed Wert) Zahl handelt.
Dann muss die Funktion eben einen vorzeichenbehafteten Wert zurückgeben.
Mark B. schrieb:> Max M. schrieb:>> Guten Abend,>>>> ich hab eine allgemeine Funktion geschrieben, die einen uint32_t-Wert>> zurück gibt. Es kann jedoch auch vorkommen, dass es sich um eine>> negative (also einen signed Wert) Zahl handelt.>> Dann muss die Funktion eben einen vorzeichenbehafteten Wert zurückgeben.
Das wird etwas schwierig, da die Funktion auch teilweise für
unsigned-Werte benutzt wird. Schade, ich dachte ich könnte das alles mit
einer Funktion abbilden.
Max M. schrieb:>> Dann muss die Funktion eben einen vorzeichenbehafteten Wert zurückgeben.>> Das wird etwas schwierig, da die Funktion auch teilweise für> unsigned-Werte benutzt wird.
Das klingt wenig sinnvoll. Und woran erkennt der Aufrufer eigentlich, ob
der Wert vorzeichenbehaftet sein soll oder nicht?
Max M. schrieb:> Das wird etwas schwierig, da die Funktion auch teilweise für> unsigned-Werte benutzt wird.
Und aus welchen Gründen brauchst du unbedingt unsigned? Wenn man es
nicht gerade mit Bitgeshifte zu tun hat oder man auf das definierte
Überlaufverhalten von unsigned angewiesen ist, sollte man versuchen bei
signed zu bleiben.
Rolf M. schrieb:> Das klingt wenig sinnvoll. Und woran erkennt der Aufrufer eigentlich, ob> der Wert vorzeichenbehaftet sein soll oder nicht?
Gar nicht, der Aufrufer bin nur ich. Ich lese Werte aus verschiedenen
Registern, laut Datenblatt ist ein Wert als short zu interpretieren, die
restlichen jedoch als unsigned short.
Das scheint broken-by-design.
Du hast einen Algorithmus und kombinierst signed und unsigned. Alles
klar.
Du hast einen anderen(!) Algorithmus, bei dem unsigned uns unsigend
kombiniert wird. Alles klar.
Also entweder überladen falls unterschiedliche Signatur oder template.
Wilhelm M. schrieb:> Also entweder überladen falls unterschiedliche Signatur oder template.
Ein Template zu verwenden, um verschiedene Integer-Resultate zu
differenzieren, ist mindestens spannend.
Es handelt sich ja wohl um unterschiedliche Algorithmen, daher wäre ein
Template-Spezialisierung eben anwendbar.
Allerdings: wir haben ja keine Ahnung, was eigentlich gemacht werden
soll...
Max M. schrieb:> Rolf M. schrieb:>> Das klingt wenig sinnvoll. Und woran erkennt der Aufrufer eigentlich, ob>> der Wert vorzeichenbehaftet sein soll oder nicht?>> Gar nicht, der Aufrufer bin nur ich. Ich lese Werte aus verschiedenen> Registern, laut Datenblatt ist ein Wert als short zu interpretieren, die> restlichen jedoch als unsigned short.
Man muss ja nicht zwingend eine einzige Funktion schreiben, die alle
Fälle abdeckt. Man darf dies sogar mit zwei oder mehr Funktionen
erledigen :-)
Vllt könnte der TO mal sagen, ob es denn nun C oder C++ sein soll. Dann
könnte man weiter kommen mit den Vorschlägen:
- unterschiedliche Funktionen/Namen (C)
- überladen, falls unterschiedliche Signatur möglich(C++)
- template spezialisierungen, falls identische Signatur (C++)
- ...
Sebastian V. schrieb:> Und aus welchen Gründen brauchst du unbedingt unsigned? Wenn man es> nicht gerade mit Bitgeshifte zu tun hat oder man auf das definierte> Überlaufverhalten von unsigned angewiesen ist, sollte man versuchen bei> signed zu bleiben.
Die Aussage interessiert mich jetzt. Weil ich behaupte, dass es genau
andersrum ist. Ich nutze immer unsigned, nur wenn ich wirklich sicher
bin signed zu brauchen nutz ich das auch.
ui schrieb:> Sebastian V. schrieb:>> Und aus welchen Gründen brauchst du unbedingt unsigned? Wenn man es>> nicht gerade mit Bitgeshifte zu tun hat oder man auf das definierte>> Überlaufverhalten von unsigned angewiesen ist, sollte man versuchen bei>> signed zu bleiben.>> Die Aussage interessiert mich jetzt. Weil ich behaupte, dass es genau> andersrum ist. Ich nutze immer unsigned, nur wenn ich wirklich sicher> bin signed zu brauchen nutz ich das auch.
Sehe ich auch so.
ui schrieb:> Sebastian V. schrieb:>> Und aus welchen Gründen brauchst du unbedingt unsigned? Wenn man es>> nicht gerade mit Bitgeshifte zu tun hat oder man auf das definierte>> Überlaufverhalten von unsigned angewiesen ist, sollte man versuchen bei>> signed zu bleiben.>> Die Aussage interessiert mich jetzt. Weil ich behaupte, dass es genau> andersrum ist. Ich nutze immer unsigned, nur wenn ich wirklich sicher> bin signed zu brauchen nutz ich das auch.
Z.B. ist ein Überlauf von signed-Variablen "undefined behavior". Der
Compiler darf also annehmen, dass das nicht auftritt. Was wesentlich
mehr Gelegenheiten zum Optimieren zur Folge hat.
ui schrieb:> Sebastian V. schrieb:>> Und aus welchen Gründen brauchst du unbedingt unsigned? Wenn man es>> nicht gerade mit Bitgeshifte zu tun hat oder man auf das definierte>> Überlaufverhalten von unsigned angewiesen ist, sollte man versuchen bei>> signed zu bleiben.>> Die Aussage interessiert mich jetzt. Weil ich behaupte, dass es genau> andersrum ist. Ich nutze immer unsigned, nur wenn ich wirklich sicher> bin signed zu brauchen nutz ich das auch.
Das kann zu unerwarteten Problemen bei Berechnungen und Vergleichen
führen, wenn man dann doch einen Signed-Wert braucht und den dann mit
einem Unsigned vergleicht. So was typisches ist z.B. eine Größenangabe.
Klar, die Maximalgröße ist doppelt so groß, wenn man unsigned nimmt.
Braucht man aber einen Offset zwischen zwei Elementen, kann dieser auch
negativ sein, und es ist nicht mehr in jedem Fall möglich, einen Offset
zwischen zwei beliebigen Elementen anzugeben - zumindest nicht ohne
einen Wrap-Around.
Man kriegt bei Vergleichen oder Berechnungen mit gemischt signed und
unsigned auch eine Warnung vom GCC deswegen.
Das hat sogar dazu geführt, dass Sprachen wie z.B. Java unsigned-Typen
nicht mal kennen (was ich aber auch für Blödsinn halte).
Rolf M. schrieb:> Das kann zu unerwarteten Problemen bei Berechnungen und Vergleichen> führen, wenn man dann doch einen Signed-Wert braucht und den dann mit> einem Unsigned vergleicht.
Das stimmt. Allerdings gilt auch das:
tictactoe schrieb:> Z.B. ist ein Überlauf von signed-Variablen "undefined behavior".
Damit ist aber "offiziell" kein free-running-counter (a la Systicker)
mehr möglich.
Zudem ist jede Division durch 2^n eine echte Division (statt shift), da
die Zahl ja negativ sein könnte.
Bitte versteh mich nicht falsch, ich finde diese
signed/unsigned-Probleme als mit die schlimmsten bei C. Wie man sich
auch entscheidet, es holt einen ein.
Max M. schrieb:> Gar nicht, der Aufrufer bin nur ich. Ich lese Werte aus verschiedenen> Registern, laut Datenblatt ist ein Wert als short zu interpretieren, die> restlichen jedoch als unsigned short.
Warum gibst du dann keinen signed Typen zurück, der größer als unsigned
short ist? Also long?
Das Problem gibt es doch schon bei der Standardfunktion getc.
Die liefert Zeichen als positive int-Werte zurück, obwohl char selber
häufig signed ist.
Spielt bei ASCII keine Rolle, aber bei den allermeisten Erweiterungen
gibt es Probleme.