C++ 双精度浮点数转字节数组

3
我希望将 double 数字转换为字节数组(无符号 char*)。
std::vector<unsigned char*> v;

    for (int i = 0; i < 5; i++)
    {

        double a = 3.14+i;
        double b = 4.44+i;

        v.push_back((unsigned char*)&a);
        v.push_back((unsigned char*)&b);
    }

    for (int i = 0; i < v.size(); i++)
        std::cout << *((double*)v.at(i)) << std::endl;

我做了这件事,但它总是给我最后一组数字。
当前输出:
7.14 8.44 7.14 8.44 7.14 8.44 7.14 8.44 7.14 8.44
正确的输出应该是:
3.14 4.44 4.14 5.44 5.14 6.44 6.14 7.44 7.14 8.44

vector<T*> 是指针的向量,而不是 T 的向量。 - Ulrich Eckhardt
兴趣所在,您为什么要这样做呢?为什么不只存储一个双精度的向量呢? - Sean
不是答案,但是可以在不改变太多的情况下解决您的问题:1ab声明为double *2 使用new double(whatever + i)进行初始化。 3 在接下来的几行中去掉它们后面的&符号。 - Utkan Gezer
5个回答

3

std::vector<unsigned char*>是一个指向unsigned char的指针列表。这不是你想要的。

我猜你想要的是std::vector<unsigned char>(这里没有指针)。

对于要添加到列表中的每个数字,您必须添加几个字节(通常为8个)。为了做到这一点,最简单的方法是:

const unsigned char* ptr = reinterpret_cast<const unsigned char*>(&a);
for (size_t i = 0; i < sizeof(double); ++i)
    v.push_back(ptr[i]);

从字节数组中提取数字的方法:
for (int i = 0; i < v.size(); i++) {
    double number;
    memcpy(&number, &v.at(i * sizeof(double)), sizeof(double));
    std::cout << number << std::endl;
}

1
你正在将临时变量a和b的地址添加到向量中。在你的示例中(碰巧),在每次循环中a和b被分配到相同的位置(一般来说,这种行为是不明确定义的,它们可能被分配到不同的位置,或者它们甚至可能在稍后重新分配,因此指针可能指向其他变量),所以当你打印v[i]指向的内容时,你总是得到最后一个迭代中a和b的内容。
编辑: 看看NetVipeC的回答,他解释得更好 :-)

我不了解C++标准,但如果它们在这方面与C类似,那么赋值仅仅是由于偶然而发生在同一位置上,而不是由于某种语言规范。 - Utkan Gezer
@ThoAppelsin,你说得完全正确,这只是偶然。我的意思是,我会编辑答案以反映这一点。谢谢你注意到了这一点。 - triple_r

1
这样做是非常错误的,你正在保存指向超出作用域的地址(a和b),这会导致无效的内存访问(可能会按预期工作,也可能不会)。
你声明了一个指针向量(std::vector),而不是unsigned char向量(std::vector)。
根据此示例的输出,似乎GCC(版本4.9.0)在循环中重复使用变量a和b的内存,或者提取了循环的变量。因为它只打印了向量中指针存储的两个不同地址。
#include <vector>
#include <iostream>

int main() {
    std::vector<unsigned char*> v;

    for (int i = 0; i < 5; i++) {

        double a = 3.14 + i;
        double b = 4.44 + i;

        v.push_back((unsigned char*)&a);
        v.push_back((unsigned char*)&b);
    }

    for (int i = 0; i < v.size(); i++) {
        std::cout << std::hex << ((double*)v.at(i)) << std::dec << std::endl;
        std::cout << *((double*)v.at(i)) << std::endl;
    }
}

输出:

0x22fec0  -> Address 1
7.14
0x22fec8  -> Address 2
8.44
0x22fec0  -> Address 1
7.14
0x22fec8  -> Address 2
8.44
0x22fec0  -> Address 1
7.14
0x22fec8  -> Address 2
8.44
0x22fec0  -> Address 1
7.14
0x22fec8  -> Address 2
8.44
0x22fec0  -> Address 1
7.14
0x22fec8  -> Address 2
8.44

0
如果你想要得到你所期望的,使用new运算符来创建双精度数。
#include <iostream>
#include <vector>
using namespace std;

int main(){

    std::vector<unsigned char*> v;

    for (int i = 0; i < 5; i++)
    {

        double *a = new double (3.14+i);
        double *b = new double (4.44+i);

        v.push_back((unsigned char*) a);
        v.push_back((unsigned char*) b);
    }

    for (int i = 0; i < v.size(); i++)
        std::cout << *((double*)v.at(i)) << std::endl;

    // remember to free the spaces you've allocated
    for (int i = 0; i < v.size(); i++)
        delete v.at(i);
}

-2

先将双精度数转换为字符串,然后从字符串中读取每个字符到字符数组中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接