C ++:为什么值赋值解释总是int?

时间:2015-06-25 19:49:39

标签: c++ variable-assignment floating-point-precision interpretation

我想为这样的变量赋值:

double var = 0xFFFFFFFF;

结果var获得分配的值65535.0。由于编译器采用64位目标系统,因此数字文字(即所有相应的32位)被解释为有效位和精确位。但是,由于0xFFFF FFFF只是一个位模式的符号,没有任何关于表示的提示,因此w.r.t可能会有不同的解释。成为浮点值。因此,我想知道是否有办法操纵这个固定的价值解释。换句话说,给出关于所需表示的提示。 (也许有人也可以指出我参与定义这种隐式解释的标准)。

到目前为止,我系统的默认精度解释似乎是

(int)0xFFFFFFFF x 10 0

enter image description here 只有分数字段被填充 1

所以也许(这里:对于16位交叉编译)我希望它是一个不同的表示形式,如:

(int)0xFFFFFF x 10 (int)0xFF

(暂时忽略符号位)。

因此我的问题是:如何强制对十六进制文字符号进行自定义双重解释?

1即使我的十六进制文字是0xFFFF FFFF FFFF FFFF,该值也只被解释为小数部分 - 所以很清楚,比特应该用于指数和符号字段。但似乎文字被切断了。

3 个答案:

答案 0 :(得分:3)

  

"我想知道是否有办法操纵这种解释。"

是的,您可以使用reinterpret_cast<double&>通过地址,强制从内存中的某个位模式进行类型(重新)解释。

  

&#34;因此我的问题:如何强制对十六进制表示法进行双重解释?&#34;

您还可以使用联合,以使其更清晰:

union uint64_2_double {
    uint64_t bits;
    double dValue;
};

uint64_2_double x;
x.bits = 0x000000000000FFFF;

std::cout << x.dValue << std::endl;

答案 1 :(得分:3)

似乎没有直接的方法来初始化具有十六进制模式的double变量,c样式强制转换等同于C ++ static_castreinterpret_cast会抱怨它无法执行转换。我将给你两个选项,一个简单的解决方案,但不会直接初始化变量,而是一个复杂的变量。您可以执行以下操作:

double var; *reinterpret_cast<long *>(&var) = 0xFFFF;

注意:注意我希望你想要初始化double的所有64位,你的常量0xFFFF似乎很小,它给出3.23786e-319

以0x开头的文字值是unsigned int类型的十六进制数。你应该使用后缀ul来使它成为无符号long的文字,在大多数架构中,这意味着64位无符号;或者,#include <stdint.h>并执行uint64_t(0xABCDFE13)

现在对于复杂的东西:在旧的C ++中,你可以编写一个函数,将积分常量转换为double,但它不会是constexpr

constexpr个功能中,您无法reinterpret_cast。然后,你使constexpr转换器加倍的唯一选择是在中间使用一个联合,例如:

struct longOrDouble {
    union {
        unsigned long asLong;
        double asDouble;
    };
    constexpr longOrDouble(unsigned long v) noexcept: asLong(v) {}
};

constexpr double toDouble(long v) { return longOrDouble(v).asDouble; }

这有点复杂,但这回答了你的问题。现在,你可以写: double var = toDouble(0xFFFF) 这会将给定的二进制模式插入到double中。

使用union写入一个成员并从另一个成员读取是C ++中未定义的行为,这里有一个很好的问题和优秀的答案: Accessing inactive union member and undefined behavior?

答案 2 :(得分:3)

C ++没有为double指定内存中表示,而且,它甚至没有指定整数类型的内存中表示(并且在具有不同结尾的系统上它实际上可能不同)。因此,如果您想将字节0xFF0xFF解释为double,您可以执行以下操作:

uint8_t bytes[sizeof(double)] = {0xFF, 0xFF};
double var;
memcpy(&var, bytes, sizeof(double));

请注意,严格来说,使用联合或reinterpret_cast指针是未定义的行为,但实际上也有效。