简体   繁体   English

为什么将“ double”表示为整数?

[英]Why is “double” represented as integer?

void foo(double a) {  
  ...
}

And in main() I passed 107.0 to foo as its parameter. main()我将107.0传递给foo作为其参数。 Then I used gdb to examine the binary representation of a by p /ta , and this is what I got: 然后,我使用gdb来检查p /taa的二进制表示形式,这就是我得到的:

$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 . 这是INTEGER 107的二进制表示但这里的类型a被定义为double和我们传递的参数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? 谁能解释为什么a具有整数二进制表示而不是double? Is the compiler doing anything funny? 编译器做任何有趣的事情吗?

You told gdb to print it as a binary integer. 您告诉gdb将其打印为二进制整数。

 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. x将值的位视为整数,并以十六进制打印整数。

d Print as integer in signed decimal. d打印为带符号十进制的整数。

u Print as integer in unsigned decimal. 用无符号十进制打印为整数。

o Print as integer in octal. o打印为八进制整数。

t Print as integer in binary. t以二进制形式打印为整数。 The letter `t' stands for "two". 字母“ t”代表“两个”。 (2) (2)

a Print as an address, both absolute in hexadecimal and as an offset from the nearest preceding symbol. a以地址形式打印,既可以是绝对的十六进制形式,也可以是距最近的前一个符号的偏移量。 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. c将其视为整数并将其打印为字符常量。

f Regard the bits of the value as a floating point number and print using typical floating point syntax. f将值的位视为浮点数,并使用典型的浮点语法进行打印。

For example, to print the program counter in hex (see section Registers), type p/x $pc 例如,要以十六进制打印程序计数器(请参阅寄存器部分),请键入p/x $pc

Doubles are represented in powers of two, just a bit different than integers. 双精度数以2的幂表示,与整数略有不同。 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. 不用多说,107就是1.101011 *(2 ^ 6)=1101011。gdb可能只显示最后一个结果,而无缘无故为您提供完整的64位表示。

well im not familiar with gdb, but when you write "d" it might think that you explicitly mean integers 我不太熟悉gdb,但是当您写“ d”时,它可能会认为您明确表示整数

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. c会让您感到困惑,因为您告诉它给它一个整数,但实际上给它一个双精度数。

There are several ways to print variables' values from the gdb command line. 有几种方法可以从gdb命令行打印变量的值。

  • print works on expressions, and will do some implicit conversions, just as C does. print对表达式有效,并且会像C一样进行一些隐式转换。
    p /ta in your example will convert a's value to an integer and print it in base 2. 您的示例中的p /ta将a的值转换为整数,并以2为底打印。
    You wanted to look at a 's bit pattern, so there are a few options with print : 您想查看a的位模式,因此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. 您可以将其地址uint64_t为与双uint64_t长度(在您的示例中可能是unsigned long longuint64_t长度相同的无符号整数类型的指针,然后取消引用。
      (gdb) p /t *(uint64_t *)&a
      $6 = 100000001011010110000000000000000000000000000000000000000000000
    • You can use {uint64_t} to accomplish the same thing more concisely. 您可以使用{uint64_t}更简洁地完成同一件事。
      (gdb) p /t {uint64_t}&a
      $7 = 100000001011010110000000000000000000000000000000000000000000000
  • x displays the data at a given address, and you can specify the datatype. x显示给定地址的数据,您可以指定数据类型。 /g means an 8-byte integer. /g表示8字节整数。
    (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. 如果您使用优化,则a可能在寄存器中,并且您将无法获取其地址,因此上述方法均无效。

(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支持使用类似于数组C联合的语法以各种格式打印AVX寄存器的内容。

(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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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