【发布时间】:2013-01-28 16:14:36
【问题描述】:
编辑:跳到我最新版本问题的水平线下方。
仅假设 sizeof(double) * CHAR_BITS
union u {
std::int64_t m_int;
double m_double;
};
int main()
{
double d = get_a_random_double();
u u1;
u1.m_double = d;
u u2;
u2.m_int = u1.m_int;
assert(u2.m_double == d);
}
我担心标准可能无法保证 int64_t 值的副本会保留我们用来保存双精度的所有位。
另一方面,我很确定标准保证以下使用 chars 而不是 unt64_t 的替代方案始终满足断言:
struct chars {
char m_x[sizeof(double)];
};
union u {
chars m_chars;
double m_double;
};
int main()
{
double d = get_a_random_double();
u u1;
u1.m_double = d;
u u2;
u2.m_chars = u1.m_chars;
assert(u2.m_double == d);
}
你同意吗?
编辑:
好的,我必须承认标准不支持通过联合进行的转换。
那么我尝试在不使用联合的情况下通过一系列字符传输双精度数的情况如何:
int main()
{
double d, e;
char c[sizeof(double)];
char* p_d = static_cast<char*>(static_cast<void*>(&d));
char* p_e = static_cast<char*>(static_cast<void*>(&e));
d = get_a_random_double();
// double -> chars
std::copy(p_d, p_d+sizeof(double), c);
// chars -> double
std::copy(c, c+sizeof(double), p_e);
assert(e == d);
}
这个标准是否保证始终满足断言?
编辑:是的!参见 C++11 3.9/2“类型”
下一个我尝试在不使用联合的情况下通过 int64_t 传输双槽的情况如何。
我知道 int64_t 不是 c++03 的一部分,所以让我们来谈谈 c++11。
再次注意,我假设 sizeof(double) * CHAR_BITS
int main()
{
double d, e;
std::int64_t i, j;
char c[sizeof(std::int64_t)];
char* p_d = static_cast<char*>(static_cast<void*>(&d));
char* p_e = static_cast<char*>(static_cast<void*>(&e));
char* p_i = static_cast<char*>(static_cast<void*>(&i));
char* p_j = static_cast<char*>(static_cast<void*>(&j));
d = get_a_random_double();
// double -> chars -> std::int64_t
std::copy(p_d, p_d+sizeof(double), c);
std::copy(c, c+sizeof(std::int64_t), p_i);
// std::int64_t -> std::int64_t
j = i; // <------------ Are all bits preserved here?
// std::int64_t -> chars -> double
std::copy(p_j, p_j+sizeof(std::int64_t), c);
std::copy(c, c+sizeof(double), p_e);
assert(e == d);
}
和以前一样,我的一个担忧是复制标准整数类型之一 (std::int64_t) 是否会“损坏”某些位(例如,一些不参与整数值表示的位)。或者,整数赋值是否保证总是忠实地复制整数占用的字节的所有位?
【问题讨论】:
标签: c++ double unions type-punning