Der Compiler konvertiert das Doppelliteral 3.0für Sie in einen Float. Das Endergebnis ist nicht zu unterscheiden von float a = 3.0f.
David Heffernan
6
@EdHeal: Das ist es, aber es ist nicht besonders relevant für diese Frage, bei der es um C ++ - Regeln geht.
Keith Thompson
20
Zumindest brauchst du ein ;After.
Hot Licks
3
10 Abstimmungen und nicht viel in den Kommentaren, um sie zu erklären, sehr entmutigend. Dies ist die erste Frage der OP, und wenn die Leute der Meinung sind, dass dies 10 Abstimmungen wert ist, sollte es einige Erklärungen geben. Dies ist eine gültige Frage mit nicht offensichtlichen Auswirkungen und vielen interessanten Dingen, die Sie aus den Antworten und Kommentaren lernen können.
Shafik Yaghmour
3
@HotLicks es geht nicht darum, sich schlecht oder gut zu fühlen, sicher mag es unfair erscheinen, aber das ist das Leben, sie sind schließlich Einhornpunkte. Dowvotes sind sicherlich nicht dazu gedacht, Upvotes, die Sie nicht mögen, aufzuheben, genauso wie Upvotes nicht dazu, Downvotes aufzuheben, die Sie nicht mögen. Wenn die Leute der Meinung sind, dass die Frage verbessert werden kann, sollte ein erstmaliger Fragesteller sicherlich ein Feedback erhalten. Ich sehe keinen Grund, abzustimmen, aber ich würde gerne wissen, warum andere dies tun, obwohl sie dies nicht sagen können.
Shafik Yaghmour
Antworten:
159
Es ist kein Fehler zu deklarieren float a = 3.0 : Wenn Sie dies tun, konvertiert der Compiler das Doppelliteral 3.0 für Sie in einen Float.
In bestimmten Szenarien sollten Sie jedoch die Float-Literal-Notation verwenden.
Aus Leistungsgründen:
Beachten Sie insbesondere:
float foo(float x){return x *0.42;}
Hier gibt der Compiler für jeden zurückgegebenen Wert eine Konvertierung aus (die Sie zur Laufzeit bezahlen). Um dies zu vermeiden, sollten Sie Folgendes deklarieren:
float foo(float x){return x *0.42f;}// OK, no conversion required
So vermeiden Sie Fehler beim Vergleich der Ergebnisse:
zB der folgende Vergleich schlägt fehl:
float x =4.2;if(x ==4.2)
std::cout <<"oops";// Not executed!
Wir können es mit der Float-Literal-Notation beheben:
In Punkt 1 42handelt es sich um eine Ganzzahl, die automatisch heraufgestuft wird float(und die zur Kompilierungszeit in jedem anständigen Compiler auftritt), sodass keine Leistungseinbußen auftreten. Wahrscheinlich hast du so etwas gemeint 42.0.
Matteo Italia
@ MattoItalia, ja ich meinte 42.0 ofc (bearbeitet, danke)
quantdev
2
@ChristianHackl Das Konvertieren 4.2in 4.2fkann FE_INEXACTje nach Compiler und System den Nebeneffekt haben, dass das Flag gesetzt wird. Einige (zugegebenermaßen wenige) Programme kümmern sich darum, welche Gleitkommaoperationen genau sind und welche nicht, und testen auf dieses Flag . Dies bedeutet, dass die einfache offensichtliche Transformation zur Kompilierungszeit das Verhalten des Programms ändert.
6
float foo(float x) { return x*42.0; }kann zu einer Multiplikation mit einfacher Genauigkeit kompiliert werden und wurde so von Clang kompiliert, als ich es das letzte Mal versuchte. Jedoch float foo(float x) { return x*0.1; }kann nicht auf eine einzige Single-Precision Multiplikation kompiliert werden. Vor diesem Patch war es vielleicht etwas zu optimistisch, aber nach dem Patch sollte die Konvertierung-double_precision_op-Konvertierung nur dann in single_precision_op kombiniert werden, wenn das Ergebnis immer das gleiche ist. article.gmane.org/gmane.comp.compilers.llvm.cvs/167800/match=
Pascal Cuoq
1
Wenn man einen Wert berechnen möchte, der ein Zehntel beträgt, liefert someFloatder Ausdruck someFloat * 0.1genauere Ergebnisse als someFloat * 0.1f, während er in vielen Fällen billiger als eine Gleitkommadivision ist. Zum Beispiel wird (float) (167772208.0f * 0.1) korrekt auf 16777220 anstatt auf 16777222 gerundet. Einige Compiler ersetzen doubleeine Gleitkommadivision möglicherweise durch eine Multiplikation, aber für diejenigen, die dies nicht tun (dies ist für viele, wenn auch nicht für alle Werte sicher) ) Die Multiplikation kann eine nützliche Optimierung sein, jedoch nur, wenn sie mit einem doubleKehrwert durchgeführt wird.
Supercat
22
Der Compiler wandelt eines der folgenden Literale in Floats um, da Sie die Variable als Float deklariert haben.
float a =3;// converted to floatfloat b =3.0;// converted to floatfloat c =3.0f;// float
Es wäre wichtig, wenn Sie auto(oder andere Typabzugsmethoden) verwenden, zum Beispiel:
auto d =3;// intauto e =3.0;// doubleauto f =3.0f;// float
Typen werden auch bei der Verwendung von Vorlagen abgeleitet, dies autoist also nicht der einzige Fall.
Shafik Yaghmour
14
Gleitkomma-Literale ohne Suffix sind vom Typ double . Dies wird im Entwurf des C ++ - Standardabschnitts behandelt. 2.14.4Gleitliterale :
[...] Der Typ eines schwebenden Literals ist doppelt, sofern nicht ausdrücklich durch ein Suffix angegeben. [...]
Ist es also ein Fehler , einem Float3.0 ein Doppelliteral zuzuweisen ?
float a =3.0
Nein, es ist nicht so, es wird konvertiert, was im Abschnitt 4.8Gleitkommakonvertierungen behandelt wird :
Ein Wert vom Gleitkommatyp kann in einen Wert eines anderen Gleitkommatyps konvertiert werden. Wenn der Quellwert im Zieltyp genau dargestellt werden kann, ist das Ergebnis der Konvertierung diese genaue Darstellung. Wenn der Quellwert zwischen zwei benachbarten Zielwerten liegt, ist das Ergebnis der Konvertierung eine implementierungsdefinierte Auswahl eines dieser Werte. Andernfalls ist das Verhalten undefiniert.
Dies bedeutet, dass eine Doppelkonstante implizit (dh stillschweigend) in eine Gleitkommakonstante konvertiert werden kann, selbst wenn dies an Genauigkeit verliert (dh Daten). Dies durfte aus Gründen der C-Kompatibilität und Benutzerfreundlichkeit bestehen bleiben, es ist jedoch zu beachten, wenn Sie Gleitkommaarbeiten ausführen.
Ein Qualitätscompiler warnt Sie, wenn Sie versuchen, etwas zu tun, das nicht definiert ist, nämlich eine doppelte Menge in einen Float einzufügen, die kleiner als der minimale oder größer als der maximale Wert ist, den ein Float darstellen kann. Ein wirklich guter Compiler gibt eine optionale Warnung aus, wenn Sie versuchen, etwas zu tun, das möglicherweise definiert ist, aber Informationen verlieren könnte, nämlich eine doppelte Menge in einen Float zu setzen, die zwischen den von einem Float darstellbaren Minimal- und Maximalwerten liegt, dies aber nicht kann genau als Float dargestellt werden.
Es gibt also Vorbehalte für den allgemeinen Fall, die Sie beachten sollten.
Aus praktischer Sicht sind die Ergebnisse in diesem Fall höchstwahrscheinlich dieselben, obwohl technisch eine Konvertierung erfolgt. Wir können dies sehen, indem wir den folgenden Code auf godbolt ausprobieren :
#include<iostream>float func1(){return3.0;// a double literal}float func2(){return3.0f;// a float literal}int main(){
std::cout << func1()<<":"<< func2()<< std::endl ;return0;}
und wir sehen, dass die Ergebnisse für func1und func2identisch sind, wobei sowohl clangals auch gcc:
func1():
movss xmm0, DWORD PTR .LC0[rip]
ret
func2():
movss xmm0, DWORD PTR .LC0[rip]
ret
Wie Pascal in diesem Kommentar betont, können Sie sich nicht immer darauf verlassen. Mit 0.1und 0.1fjeweils bewirkt , dass die Anordnung erzeugt zu unterscheiden , da die Umwandlung nun explizit getan werden muss. Der folgende Code:
float func1(float x ){return x*0.1;// a double literal}float func2(float x){return x*0.1f;// a float literal}
Unabhängig davon, ob Sie feststellen können, ob die Konvertierung Auswirkungen auf die Leistung hat oder nicht, dokumentiert die Verwendung des richtigen Typs Ihre Absicht besser. Verwenden Sie beispielsweise explizite Konvertierungenstatic_cast hilft auch zu verdeutlichen, dass die Konvertierung nicht versehentlich, sondern beabsichtigt war, was auf einen Fehler oder einen potenziellen Fehler hinweisen kann.
Hinweis
Wie Supercat betont, ist die Multiplikation mit zB 0.1und 0.1fnicht gleichwertig. Ich werde den Kommentar nur zitieren, weil er ausgezeichnet war und eine Zusammenfassung ihm wahrscheinlich nicht gerecht werden würde:
Wenn beispielsweise f gleich 100000224 war (was genau als Float darstellbar ist), sollte das Multiplizieren mit einem Zehntel ein Ergebnis ergeben, das auf 10000022 abgerundet wird, aber das Multiplizieren mit 0,1f ergibt stattdessen ein Ergebnis, das fälschlicherweise auf 10000023 aufrundet Wenn die Absicht besteht, durch zehn zu teilen, ist die Multiplikation mit der Doppelkonstante 0,1 wahrscheinlich schneller als die Division durch 10f und genauer als die Multiplikation mit 0,1f.
Mein ursprünglicher Punkt war es, ein falsches Beispiel zu demonstrieren, das in einer anderen Frage gegeben wurde, aber dies zeigt genau, dass subtile Probleme in Spielzeugbeispielen existieren können.
Es kann erwähnenswert sein, dass die Ausdrücke f = f * 0.1;und f = f * 0.1f;verschiedene Dinge tun . Wenn beispielsweise f100000224 gleich ist (was genau als a darstellbar ist float), sollte das Multiplizieren mit einem Zehntel ein Ergebnis ergeben, das auf 10000022 abgerundet wird, aber das Multiplizieren mit 0,1f ergibt stattdessen ein Ergebnis, das fälschlicherweise auf 10000023 aufrundet Die Absicht ist, durch zehn zu dividieren. Die Multiplikation mit der doubleKonstanten 0,1 ist wahrscheinlich schneller als die Division durch 10fund präziser als die Multiplikation mit 0.1f.
Supercat
@supercat danke für das schöne Beispiel, ich habe Sie direkt zitiert, bitte zögern Sie nicht zu bearbeiten, wie Sie es für richtig halten.
Shafik Yaghmour
4
Es ist kein Fehler in dem Sinne, dass der Compiler ihn ablehnt, aber es ist ein Fehler in dem Sinne, dass es möglicherweise nicht das ist, was Sie wollen.
Wie Ihr Buch richtig sagt, 3.0ist es ein Wert vom Typ double. Es gibt eine implizite Konvertierung von doublenach float, alsofloat a = 3.0; wie eine gültige Definition einer Variablen.
Zumindest konzeptionell führt dies jedoch eine unnötige Konvertierung durch. Je nach Compiler kann die Konvertierung zur Kompilierungszeit durchgeführt oder zur Laufzeit gespeichert werden. Ein gültiger Grund für das Speichern zur Laufzeit ist, dass Gleitkommakonvertierungen schwierig sind und unerwartete Nebenwirkungen haben können, wenn der Wert nicht genau dargestellt werden kann und es nicht immer einfach ist, zu überprüfen, ob der Wert genau dargestellt werden kann.
3.0f vermeidet dieses Problem: Obwohl der Compiler technisch immer noch die Konstante zur Laufzeit berechnen darf (es ist immer so), gibt es hier absolut keinen Grund, warum ein Compiler dies möglicherweise tun könnte.
In der Tat wäre es im Fall eines Cross-Compilers völlig falsch, wenn die Konvertierung zur Kompilierungszeit durchgeführt würde, da sie auf der falschen Plattform stattfinden würde.
Marquis von Lorne
2
Obwohl es an sich kein Fehler ist, ist es ein wenig schlampig. Sie wissen, dass Sie einen Float möchten, also initialisieren Sie ihn mit einem Float. Ein anderer Programmierer kann mitkommen und nicht sicher sein, welcher Teil der Deklaration korrekt ist, der Typ oder der Initialisierer. Warum nicht beide richtig sein?
float Antwort = 42.0f;
Wenn Sie eine Variable definieren, wird sie mit dem bereitgestellten Initialisierer initialisiert. Dies erfordert möglicherweise die Konvertierung des Werts des Initialisierers in den Typ der Variablen, die initialisiert wird. Das passiert, wenn Sie sagen float a = 3.0;: Der Wert des Initialisierers wird in konvertiert float, und das Ergebnis der Konvertierung wird zum Anfangswert vona .
Das ist im Allgemeinen in Ordnung, aber es tut nicht weh zu schreiben, um 3.0fzu zeigen, dass Sie wissen, was Sie tun, und insbesondere, wenn Sie schreiben möchten auto a = 3.0f.
Dies zeigt, dass die Größe von 3.2f auf einem 32-Bit-Computer als 4 Byte angenommen wird, während 3.2 als doppelter Wert interpretiert wird, der auf einem 32-Bit-Computer 8 Byte benötigt. Dies sollte die Antwort liefern, nach der Sie suchen.
Das zeigt das doubleund floatist anders, es antwortet nicht, ob Sie ein floataus einem Doppelliteral initialisieren können
Jonathan Wakely
Natürlich können Sie einen Float von einem doppelten Wert initialisieren, der gegebenenfalls
abgeschnitten wird
4
Ja, ich weiß, aber das war die Frage des OP, daher konnte Ihre Antwort sie nicht wirklich beantworten, obwohl Sie behaupteten, die Antwort zu geben!
Jonathan Wakely
0
Der Compiler leitet den am besten passenden Typ aus Literalen ab oder zumindest aus dem, was er für am besten geeignet hält. Das bedeutet eher Effizienzverlust gegenüber Präzision, dh Verwendung eines Double anstelle von Float. Verwenden Sie im Zweifelsfall Klammer-Intializer, um dies deutlich zu machen:
auto d =double{3};// make a doubleauto f =float{3};// make a floatauto i =int{3};// make a int
Die Geschichte wird interessanter, wenn Sie von einer anderen Variablen aus initialisieren, für die Typkonvertierungsregeln gelten: Während es legal ist, eine Doppelform als Literal zu konstruieren, kann sie nicht ohne mögliche Verengung aus einem int konstruiert werden:
auto xxx =double{i}// warning ! narrowing conversion of 'i' from 'int' to 'double'
3.0
für Sie in einen Float. Das Endergebnis ist nicht zu unterscheiden vonfloat a = 3.0f
.;
After.Antworten:
Es ist kein Fehler zu deklarieren
float a = 3.0
: Wenn Sie dies tun, konvertiert der Compiler das Doppelliteral 3.0 für Sie in einen Float.In bestimmten Szenarien sollten Sie jedoch die Float-Literal-Notation verwenden.
Aus Leistungsgründen:
Beachten Sie insbesondere:
Hier gibt der Compiler für jeden zurückgegebenen Wert eine Konvertierung aus (die Sie zur Laufzeit bezahlen). Um dies zu vermeiden, sollten Sie Folgendes deklarieren:
So vermeiden Sie Fehler beim Vergleich der Ergebnisse:
zB der folgende Vergleich schlägt fehl:
Wir können es mit der Float-Literal-Notation beheben:
(Hinweis: Auf diese Weise sollten Sie Float- oder Double-Zahlen natürlich nicht vergleichen, um die Gleichheit im Allgemeinen zu gewährleisten )
So rufen Sie die richtige überladene Funktion auf (aus demselben Grund):
Beispiel:
Wie von Cyber festgestellt , ist es in einem Typabzugskontext erforderlich, dem Compiler zu helfen, a abzuleiten
float
:Im Falle von
auto
:Und in ähnlicher Weise im Falle des Abzugs des Vorlagentyps:
Live-Demo
quelle
42
handelt es sich um eine Ganzzahl, die automatisch heraufgestuft wirdfloat
(und die zur Kompilierungszeit in jedem anständigen Compiler auftritt), sodass keine Leistungseinbußen auftreten. Wahrscheinlich hast du so etwas gemeint42.0
.4.2
in4.2f
kannFE_INEXACT
je nach Compiler und System den Nebeneffekt haben, dass das Flag gesetzt wird. Einige (zugegebenermaßen wenige) Programme kümmern sich darum, welche Gleitkommaoperationen genau sind und welche nicht, und testen auf dieses Flag . Dies bedeutet, dass die einfache offensichtliche Transformation zur Kompilierungszeit das Verhalten des Programms ändert.float foo(float x) { return x*42.0; }
kann zu einer Multiplikation mit einfacher Genauigkeit kompiliert werden und wurde so von Clang kompiliert, als ich es das letzte Mal versuchte. Jedochfloat foo(float x) { return x*0.1; }
kann nicht auf eine einzige Single-Precision Multiplikation kompiliert werden. Vor diesem Patch war es vielleicht etwas zu optimistisch, aber nach dem Patch sollte die Konvertierung-double_precision_op-Konvertierung nur dann in single_precision_op kombiniert werden, wenn das Ergebnis immer das gleiche ist. article.gmane.org/gmane.comp.compilers.llvm.cvs/167800/match=someFloat
der AusdrucksomeFloat * 0.1
genauere Ergebnisse alssomeFloat * 0.1f
, während er in vielen Fällen billiger als eine Gleitkommadivision ist. Zum Beispiel wird (float) (167772208.0f * 0.1) korrekt auf 16777220 anstatt auf 16777222 gerundet. Einige Compiler ersetzendouble
eine Gleitkommadivision möglicherweise durch eine Multiplikation, aber für diejenigen, die dies nicht tun (dies ist für viele, wenn auch nicht für alle Werte sicher) ) Die Multiplikation kann eine nützliche Optimierung sein, jedoch nur, wenn sie mit einemdouble
Kehrwert durchgeführt wird.Der Compiler wandelt eines der folgenden Literale in Floats um, da Sie die Variable als Float deklariert haben.
Es wäre wichtig, wenn Sie
auto
(oder andere Typabzugsmethoden) verwenden, zum Beispiel:quelle
auto
ist also nicht der einzige Fall.Gleitkomma-Literale ohne Suffix sind vom Typ double . Dies wird im Entwurf des C ++ - Standardabschnitts behandelt.
2.14.4
Gleitliterale :Ist es also ein Fehler , einem Float
3.0
ein Doppelliteral zuzuweisen ?Nein, es ist nicht so, es wird konvertiert, was im Abschnitt
4.8
Gleitkommakonvertierungen behandelt wird :Weitere Details zu den Auswirkungen finden Sie in GotW # 67: double oder nichts, was besagt:
Es gibt also Vorbehalte für den allgemeinen Fall, die Sie beachten sollten.
Aus praktischer Sicht sind die Ergebnisse in diesem Fall höchstwahrscheinlich dieselben, obwohl technisch eine Konvertierung erfolgt. Wir können dies sehen, indem wir den folgenden Code auf godbolt ausprobieren :
und wir sehen, dass die Ergebnisse für
func1
undfunc2
identisch sind, wobei sowohlclang
als auchgcc
:Wie Pascal in diesem Kommentar betont, können Sie sich nicht immer darauf verlassen. Mit
0.1
und0.1f
jeweils bewirkt , dass die Anordnung erzeugt zu unterscheiden , da die Umwandlung nun explizit getan werden muss. Der folgende Code:führt zu folgender Montage:
Unabhängig davon, ob Sie feststellen können, ob die Konvertierung Auswirkungen auf die Leistung hat oder nicht, dokumentiert die Verwendung des richtigen Typs Ihre Absicht besser. Verwenden Sie beispielsweise explizite Konvertierungen
static_cast
hilft auch zu verdeutlichen, dass die Konvertierung nicht versehentlich, sondern beabsichtigt war, was auf einen Fehler oder einen potenziellen Fehler hinweisen kann.Hinweis
Wie Supercat betont, ist die Multiplikation mit zB
0.1
und0.1f
nicht gleichwertig. Ich werde den Kommentar nur zitieren, weil er ausgezeichnet war und eine Zusammenfassung ihm wahrscheinlich nicht gerecht werden würde:Mein ursprünglicher Punkt war es, ein falsches Beispiel zu demonstrieren, das in einer anderen Frage gegeben wurde, aber dies zeigt genau, dass subtile Probleme in Spielzeugbeispielen existieren können.
quelle
f = f * 0.1;
undf = f * 0.1f;
verschiedene Dinge tun . Wenn beispielsweisef
100000224 gleich ist (was genau als a darstellbar istfloat
), sollte das Multiplizieren mit einem Zehntel ein Ergebnis ergeben, das auf 10000022 abgerundet wird, aber das Multiplizieren mit 0,1f ergibt stattdessen ein Ergebnis, das fälschlicherweise auf 10000023 aufrundet Die Absicht ist, durch zehn zu dividieren. Die Multiplikation mit derdouble
Konstanten 0,1 ist wahrscheinlich schneller als die Division durch10f
und präziser als die Multiplikation mit0.1f
.Es ist kein Fehler in dem Sinne, dass der Compiler ihn ablehnt, aber es ist ein Fehler in dem Sinne, dass es möglicherweise nicht das ist, was Sie wollen.
Wie Ihr Buch richtig sagt,
3.0
ist es ein Wert vom Typdouble
. Es gibt eine implizite Konvertierung vondouble
nachfloat
, alsofloat a = 3.0;
wie eine gültige Definition einer Variablen.Zumindest konzeptionell führt dies jedoch eine unnötige Konvertierung durch. Je nach Compiler kann die Konvertierung zur Kompilierungszeit durchgeführt oder zur Laufzeit gespeichert werden. Ein gültiger Grund für das Speichern zur Laufzeit ist, dass Gleitkommakonvertierungen schwierig sind und unerwartete Nebenwirkungen haben können, wenn der Wert nicht genau dargestellt werden kann und es nicht immer einfach ist, zu überprüfen, ob der Wert genau dargestellt werden kann.
3.0f
vermeidet dieses Problem: Obwohl der Compiler technisch immer noch die Konstante zur Laufzeit berechnen darf (es ist immer so), gibt es hier absolut keinen Grund, warum ein Compiler dies möglicherweise tun könnte.quelle
Obwohl es an sich kein Fehler ist, ist es ein wenig schlampig. Sie wissen, dass Sie einen Float möchten, also initialisieren Sie ihn mit einem Float.
Ein anderer Programmierer kann mitkommen und nicht sicher sein, welcher Teil der Deklaration korrekt ist, der Typ oder der Initialisierer. Warum nicht beide richtig sein?
float Antwort = 42.0f;
quelle
Wenn Sie eine Variable definieren, wird sie mit dem bereitgestellten Initialisierer initialisiert. Dies erfordert möglicherweise die Konvertierung des Werts des Initialisierers in den Typ der Variablen, die initialisiert wird. Das passiert, wenn Sie sagen
float a = 3.0;
: Der Wert des Initialisierers wird in konvertiertfloat
, und das Ergebnis der Konvertierung wird zum Anfangswert vona
.Das ist im Allgemeinen in Ordnung, aber es tut nicht weh zu schreiben, um
3.0f
zu zeigen, dass Sie wissen, was Sie tun, und insbesondere, wenn Sie schreiben möchtenauto a = 3.0f
.quelle
Wenn Sie Folgendes ausprobieren:
Sie erhalten folgende Ausgabe:
Dies zeigt, dass die Größe von 3.2f auf einem 32-Bit-Computer als 4 Byte angenommen wird, während 3.2 als doppelter Wert interpretiert wird, der auf einem 32-Bit-Computer 8 Byte benötigt. Dies sollte die Antwort liefern, nach der Sie suchen.
quelle
double
undfloat
ist anders, es antwortet nicht, ob Sie einfloat
aus einem Doppelliteral initialisieren könnenDer Compiler leitet den am besten passenden Typ aus Literalen ab oder zumindest aus dem, was er für am besten geeignet hält. Das bedeutet eher Effizienzverlust gegenüber Präzision, dh Verwendung eines Double anstelle von Float. Verwenden Sie im Zweifelsfall Klammer-Intializer, um dies deutlich zu machen:
Die Geschichte wird interessanter, wenn Sie von einer anderen Variablen aus initialisieren, für die Typkonvertierungsregeln gelten: Während es legal ist, eine Doppelform als Literal zu konstruieren, kann sie nicht ohne mögliche Verengung aus einem int konstruiert werden:
quelle