2013-02-23 8 views
14

Wenn ich das folgende C++ - Programm in einem 32-Bit-PowerPC-Kernel ausführe, der Software-Floating-Emulation unterstützt (Hardwarefließkomma deaktiviert), bekomme ich eine falsche bedingte Auswertung. Können mir einige sagen, was das mögliche Problem ist?Falsches Gleitkomma-Verhalten

#include <stdio.h> 

int main() { 
    int newmax = 1; 
    if ((newmax + 0.0) > 256) { 
     printf("\nShouldn't be here\n"); 
    } else { 
     printf("\nShould be here\n"); 
    } 
} 

Compile:

powerpc-linux-g++ -msoft-float -c floating.cxx 
powerpc-linux-g++ -o floating floating.o 

Ausgabe im Zielsystem:

[linux:/]$ ./floating 
Shouldn't be here 
+0

Können Sie mir sagen, was Kernel ist das? Meine beste Vermutung ist, dass seine Emulation irgendwie dem Gleitkommastandard nicht gehorcht und eine ungenaue Darstellung von Null hat. Bedenken Sie auch, dass 0.0 standardmäßig doppelt ist und nicht float. Vielleicht unterstützt Ihr Software-Emulator kein Double. – speeder

+2

Sie sollten -msoft-float auch beim Linken angeben. –

+0

@speeder. Dies ist ein benutzerdefinierter Kernel 2.6.32.59. Ich bezweifle auch, dass dies ein Softwareemulationsproblem im Kernel sein könnte. – rajachan

Antwort

1

Sie sollten auch -msoft-float angeben, wenn uns Verknüpfung Geben Sie hat schriftlich mit der -S-Flag : powerpc-linux-g ++ -msoft-float -c floating.cxx -S -o Floating.s

0

Erstens, warum Hardware Fließkomma deaktiviert ist?

Aufgrund dieses Typs können Würfe in falscher Reihenfolge ausgeführt werden.

(double)1 = 0x3FF0000000000000 
(float) 1 = 0x3F800000 

Dies ist Ihre Bedingung.

if ((newmax + 0.0) > 256) 

In Ihrem Fall: 1) Newmax Gießen zu schweben oder Doppel; 2) Hinzufügen von 0.0; 3) Wertzuweisung zurück an int.

Es hängt von Ihrer Maschine ab, aber Int ist normalerweise 32-Bit-Wert. Um es zu überprüfen können Sie:

int i; 
printf("%d", sizeof(i)); 

Wie auch immer, um Ihr Problem zu gehen zurück, nach berechneter Wert Umwandlung in int Sie große positive Zahl zu bekommen. In Ihrer Situation würde ich ausdrucken/oder vergleichen nicht mit 0x100 aber mit

0x3F800000, 0x3FF0000000000000, 0x3FF00000

Um das herauszufinden, was passiert ist, aber Auseinanderbauen ist die beste Option.

Wahrscheinlich war es nicht so hilfreich, aber das war nur meine Idee, was passiert ist.

+0

Die Reihenfolge, in der Typumwandlungen ausgeführt werden, wird vom C++ - Standard angegeben. Es ist nicht wichtig, ob Gleitkommaoperationen mit SW oder HW oder einer Mischung daraus ausgeführt werden. – MSalters

-1

Die Anweisung in Ihrem Code newmax + 0.0 erzeugt ein Ergebnis in float oder double, wird aber mit einem ganzzahligen Wert verglichen.

also dieser Fehler.

Probieren Sie dies aus,

int i=1; 
printf("%d",(i+0.0)); 

Sie ganz gleich ein Ergebnis 0 jedes Mal bekommen, was der Wert von i. Ange

int i=1; 
printf("%f",(i+0.0)); 

Dies erzeugt 1,0000

0

Dieses alles von Compiler-Fehler zu Assembler Fehler sein könnte Fehler Linkerfehler auf Kernel. Andere Leute haben bereits darauf hingewiesen: Compiler-Fehler - die wahrscheinlichste Quelle für diesen Fehler - könnten verifiziert werden (oder ausgeschlossen werden), wenn Sie die Ausgabe der Kompilierung mit der Option -S zur Verfügung gestellt haben.Wenn es sich nicht um einen Compilerfehler handelt, wäre ein Kernelfehler mit der Gleitkommaemulation die nächste wahrscheinliche Ursache des Problems.