简体   繁体   中英

Why is “double” represented as integer?

void foo(double a) {  
  ...
}

And in main() I passed 107.0 to foo as its parameter. Then I used gdb to examine the binary representation of a by p /ta , and this is what I got:

$1 = 1101011

This results seems very strange to me. This is the binary representation of INTEGER 107. But here the type of a is defined as double and we passed a parameter of 107.0 . And we know that doubles have different binary representations as integers.

Can anyone explain why a has a integer binary rep rather than double? Is the compiler doing anything funny?

You told gdb to print it as a binary integer.

 p /t a

If you want to see the floating point version use

 p /f a

Output formats

x Regard the bits of the value as an integer, and print the integer in hexadecimal.

d Print as integer in signed decimal.

u Print as integer in unsigned decimal.

o Print as integer in octal.

t Print as integer in binary. The letter `t' stands for "two". (2)

a Print as an address, both absolute in hexadecimal and as an offset from the nearest preceding symbol. You can use this format used to discover where (in what function) an unknown address is located:

c Regard as an integer and print it as a character constant.

f Regard the bits of the value as a floating point number and print using typical floating point syntax.

For example, to print the program counter in hex (see section Registers), type p/x $pc

Doubles are represented in powers of two, just a bit different than integers. Not going into much details, 107 would be 1.101011 * (2^6) = 1101011. It is possible that gdb only shows the last result instead of giving you the full 64bit representation for no reason.

well im not familiar with gdb, but when you write "d" it might think that you explicitly mean integers

consider:

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

c will be confused because you tell it you will give it an integer but you actually give it a double.

There are several ways to print variables' values from the gdb command line.

  • print works on expressions, and will do some implicit conversions, just as C does.
    p /ta in your example will convert a's value to an integer and print it in base 2.
    You wanted to look at a 's bit pattern, so there are a few options with print :

    • you can cast its address to a pointer to an unsigned integer type that's the same length as a double - probably unsigned long long or uint64_t in your example - and dereference that.
      (gdb) p /t *(uint64_t *)&a
      $6 = 100000001011010110000000000000000000000000000000000000000000000
    • You can use {uint64_t} to accomplish the same thing more concisely.
      (gdb) p /t {uint64_t}&a
      $7 = 100000001011010110000000000000000000000000000000000000000000000
  • x displays the data at a given address, and you can specify the datatype. /g means an 8-byte integer.
    (gdb) x /tg &a
    0x7fffffffded8: 0100000001011010110000000000000000000000000000000000000000000000

If you use optimization, it's possible that a will be in a register, and you won't be able to take its address, so none of the above will work.

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

But gdb supports printing the contents of AVX registers in various formats, using syntax resembling a C union of arrays.

(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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM