Es ist bekannt, dass in C Gleitkomma-Literale (z . B. 1.23
) einen Typ haben double
. Infolgedessen wird jede Berechnung, die sie betrifft, auf das Doppelte hochgestuft.
Ich arbeite an einem eingebetteten Echtzeitsystem mit einer Gleitkommaeinheit, die nur float
Zahlen mit einfacher Genauigkeit ( ) unterstützt. Alle meine Variablen sind float
, und diese Genauigkeit ist ausreichend. Ich brauche (und kann es mir überhaupt nicht leisten) double
. Aber jedes Mal so etwas
if (x < 2.5) ...
geschrieben ist, passiert eine Katastrophe: Die Verlangsamung kann bis zu zwei Größenordnungen betragen. Die direkte Antwort ist natürlich zu schreiben
if (x < 2.5f) ...
Dies ist jedoch so leicht zu übersehen (und bis zu spät schwer zu erkennen), insbesondere wenn ein ' #define
disziplinierter ' Wert von einem weniger disziplinierten (oder nur neuen) Entwickler in einer separaten Datei gespeichert wird.
Gibt es also eine Möglichkeit, den Compiler zu zwingen, alle (Gleitkomma-) Literale wie mit einem Suffix als float zu behandeln f
? Auch wenn es gegen die Spezifikationen ist, ist es mir egal. Oder irgendwelche anderen Lösungen? Der Compiler ist übrigens gcc.
quelle
-Wdouble-promotion
, die Ihnen zumindest Warnungen geben werden. Kombiniert mit-Wfloat-conversion
sollte eine ziemlich gute Abdeckung ergeben.f
s aus FP-Literalen einzufügen .Antworten:
-fsingle-precision-constant
Flag kann verwendet werden. Dadurch werden Gleitkommakonstanten mit einfacher Genauigkeit geladen, auch wenn dies nicht genau ist.Hinweis: Hierbei werden auch Konstanten mit einfacher Genauigkeit bei Operationen mit Variablen mit doppelter Genauigkeit verwendet.
quelle
x < 2.5
, alles wird in Ordnung sein. Er wird wahrscheinlich diese spezielle Compiler-Option verpassen, die ihm das Leben rettet :-). Wenn er stattdessen Warnungen erhält (mit-Wdouble-promotion
,-Wfloat-conversion
) und Sie verwenden-Werror
, die alle Warnungen in Fehler umwandeln, checkt er den Code möglicherweise nicht direkt ein und wundert sich möglicherweise und lernt. Aber nur für die Release-Qualität möchten Sie vielleicht auf Nummer sicher gehen und sie mit der spezifischen Option (-fsingle-precision-constant
) kompilieren . Bitte beachten Sie, dass dies nur ein Kommentar ist.Verwenden Sie stattdessen Warnungen:
-Wdouble-promotion
Warnt vor implizitem Float, um die Promotion zu verdoppeln, wie in Ihrem Beispiel.-Wfloat-conversion
warnt vor Fällen, in denen Sie Floats möglicherweise noch Doppelte zuweisen.Dies ist eine bessere Lösung, als einfach doppelte Werte auf den nächsten Gleitkommawert zu zwingen. Ihr Gleitkomma-Code ist immer noch kompatibel und Sie werden keine bösen Überraschungen erleben, wenn ein Doppelwert einen positiven Wert enthält, beispielsweise kleiner als
FLT_DENORM_MIN
(unter der Annahme von IEEE-754) oder größer alsFLT_MAX
.quelle
-fsingle-precision-constant
funktioniert es jedoch besser. Erstens hat meine Version von GCC (4.4.7) einfach keine dieser Optionen. Zweitens habe ich keine kniffligen Konstanten (außer NaN) und alle Berechnungen müssenfloat
sowieso sein (das ist der springende Punkt). Schließlich generiert die mitgelieferte Chipbibliothek so viele Warnungen (die meisten davon explizit!), Dass die nützlichen häufig im Stapel vergraben werden ... Und wie gesagt, ich bin in diesem Fall nicht sehr besorgt über die strikte Einhaltung.Sie können die definierten Konstanten
(float)
überall dort umwandeln, wo sie verwendet werden. Der Optimierer sollte seine Aufgabe erfüllen. Dies ist eine tragbare Lösung.#define LIMIT 2.5 if (x < (float)LIMIT) ...
quelle
Das
-Wunsuffixed-float-constants
Flag könnte auch verwendet werden, möglicherweise kombiniert mit einigen der anderen Optionen in der oben akzeptierten Antwort. Dies fängt jedoch wahrscheinlich keine nicht angehängten Konstanten in Systemheadern ab. Müsste auch verwenden-Wsystem-headers
, um diese zu fangen. Könnte viele Warnungen erzeugen ...quelle