2016-04-20 16 views
0
void foo(double a) { 
    ... 
} 

Und in main() habe ich 107.0 zu foo als Parameter übergeben. Dann habe ich gdb die binäre Darstellung von a von p /t a zu untersuchen, und das ist, was ich habe:Warum wird "double" als Integer dargestellt?

$1 = 1101011 

Diese Ergebnisse scheinen mir sehr seltsam. Dies ist die binäre Darstellung von INTEGER 107. Aber hier ist der Typ von a definiert als double und wir haben einen Parameter von 107.0 übergeben. Und wir wissen, dass Doubles unterschiedliche Binärdarstellungen als Ganzzahlen haben.

Kann jemand erklären, warum a eine Ganzzahl binär rep eher als doppelt hat? Tut der Compiler etwas Lustiges?

+1

'/ t' bedeutet nicht das Drucken des Bitmusters, es bedeutet nur eine Basis 2 Darstellung des Wertes, der Wert selbst ist 107 (gdb kennt den Typ Ihres' a'). Um das Bitmuster herauszufinden, verwenden Sie den Befehl 'x'. – ach

Antwort

1

Doppel sind in Zweierpotenzen dargestellt, nur ein bisschen anders als ganze Zahlen. Wenn ich nicht auf Details eingehe, wäre 107 1.101011 * (2^6) = 1101011. Es ist möglich, dass gdb nur das letzte Ergebnis anzeigt, anstatt Ihnen die volle 64-Bit-Darstellung ohne Grund zu geben.

+0

Das 'd' war ein Tippfehler. Siehe meine aktualisierte Frage. – OneZero

0

gut im mit GDB nicht vertraut, aber wenn Sie „d“ schreiben könnte es denken, dass Sie explizit ganze Zahlen bedeuten

betrachten:

double foo = 1.0; 
printf("%d",foo); 

c wird verwirrt sein, weil Sie es sagen, Sie geben es ist eine ganze Zahl, aber Sie geben es tatsächlich ein Doppel.

+0

Das 'd' war ein Tippfehler. Siehe meine aktualisierte Frage. – OneZero

5

Sie sagten gdb, es als binäre Ganzzahl zu drucken.

p /t a 

Wenn Sie wollen, dass die Gleitkommaversion

p /f a 

Output formats

x Regard die Bits des Wertes als eine ganze Zahl, und drucken Sie die ganze Zahl in hexadezimal verwenden, um zu sehen.

d Druck als Ganzzahl in vorzeichenbehafteter Dezimalzahl.

u Druck als Ganzzahl in vorzeichenloser Dezimalzahl.

o Druck als Ganzzahl in Oktal.

t Druck als Ganzzahl im Binärformat. Der Buchstabe "t" steht für "zwei". (2)

a Als Adresse drucken, sowohl absolut in Hexadezimal als auch als Offset vom nächsten vorhergehenden Symbol. Sie können dieses an verwendete Format verwenden, um herauszufinden, wo (in welcher Funktion) sich eine unbekannte Adresse befindet:

c Als Ganzzahl betrachten und als Zeichenkonstante ausgeben.

f Beachten Sie die Bits des Werts als Fließkommazahl und drucken Sie mit der typischen Fließkomma-Syntax.

Zum Beispiel der Programmzähler in hex zu drucken (siehe Abschnitt Register), Typ p/x $pc

+0

Sorry, das war ein Tippfehler. Ich habe tatsächlich 'p/t a' benutzt. Aber in jedem Fall ist der Formatbezeichner '\ t', der besagt, dass er als Binärdatei gedruckt werden soll. So dient das ursprüngliche typo'ed "d" nur als ein variabler Name. – OneZero

+0

@OneZero-Webseite sagt, es sollte ein Schrägstrich sein Um beispielsweise den Programmzähler in Hex auszudrucken (siehe Abschnitt Register), geben Sie 'p/x $ pc' ein – sabbahillel

0

Es gibt mehr Möglichkeiten, Variablen Werte aus der GDB-Befehlszeile zu drucken.

  • print Arbeiten auf Ausdrücke und werden einige implizite Konvertierungen tun, ebenso wie C der Fall ist.
    p /t a in Ihrem Beispiel einen Wert auf eine ganze Zahl und drucken es in Basis 2
    Sie wandeln auf a ‚s Bitmuster, so gibt es ein paar Optionen mit print aussehen wollte:

    • Sie können ihre Adresse auf einen Zeiger auf einen vorzeichenlosen Integer-Typ mit der gleichen Länge wie in einem Double-Format - wahrscheinlich unsigned long long oder uint64_t in Ihrem Beispiel - umwandeln und dies dereferenzieren.
      (gdb) p /t *(uint64_t *)&a
      $6 = 100000001011010110000000000000000000000000000000000000000000000
    • können Sie {uint64_t} verwenden, um die gleiche Sache prägnanter zu erreichen.
      (gdb) p /t {uint64_t}&a
      $7 = 100000001011010110000000000000000000000000000000000000000000000
  • x zeigt die Daten an einer bestimmten Adresse, und Sie können den Datentyp angeben. /g bedeutet eine 8-Byte-Ganzzahl.
    (gdb) x /tg &a
    0x7fffffffded8: 0100000001011010110000000000000000000000000000000000000000000000

Wenn Sie Optimierung verwenden, ist es möglich, dass a in einem Register sein, und Sie werden nicht in der Lage sein, seine Adresse zu nehmen, so dass keiner der oben arbeiten.

(gdb) p {uint64_t}&a 
Address requested for identifier "a" which is in register $ymm0 

Aber gdb unterstützt den Inhalt von AVX Registern in verschiedenen Formaten drucken, Syntax unter Verwendung einer C Union von Anordnungen ähnelt.

(gdb) p $ymm0 
$1 = {v8_float = {0, 3.41796875, 0, 0, 0, 0, 0, 0}, 
v4_double = {107, 0, 0, 0}, v32_int8 = {0, 0, 0, 0, 0, -64, 90, 
64, 0 <repeats 24 times>}, 
v16_int16 = {0, 0, -16384, 16474, 0 <repeats 12 times>}, 
v8_int32 = {0, 1079689216, 0, 0, 0, 0, 0, 0}, 
v4_int64 = {4637229872563879936, 0, 0, 0}, 
v2_int128 = {0x0000000000000000405ac00000000000, 0x00000000000000000000000000000000}} 

(gdb) p /t $ymm0.v4_int64[0] 
$2 = 100000001011010110000000000000000000000000000000000000000000000 
Verwandte Themen