【问题标题】:Convert data from const void *data to double将数据从 const void *data 转换为 double
【发布时间】:2014-09-12 22:10:33
【问题描述】:

我从其他函数接收到 myfunction(const void *data) 的数据,其中指针 data 存储像 {0,0,0,0,0,0,0,40,20,0,0,0,0,0,0} 这样的值。

我只想访问来自 {40,20,0,0,0,0,0,0} 的值并转换为应该给出 8.0double 类型值。为了访问和转换为 double 类型,我尝试了指向 double 的指针:

double* dptr;
dptr=&(*data+8);
dptr;

这给出了类似的错误

“错误:‘const void*’不是指向对象的指针类型”

【问题讨论】:

    标签: c++ c pointers void-pointers


    【解决方案1】:

    在 C 中,您不能取消引用 void 指针。 因此,您可以键入强制转换 void 指针并使用它。 像这样的东西 dptr=((double*)data+8);所以现在将无效的数据视为双指针。

    【讨论】:

    • @ Ginu Jacob 我希望这 8 个字节 40,20,0,0,0,0,0,0 加倍值 8.0 我尝试了你的建议但仍然有问题,因为我在分配时会感到困惑第 8 个元素的地址,dptr 也将采用其他值来提供双精度类型结果,如 (0x4020000000000000) 8.0。你能提供一些建议吗..
    • 这取决于您的输入数组。假设您的数组 {0,0,0,0,0,0,0,40,20,0,0,0,0,0,0} 不是双倍的,它会给您错误的结果。这是因为当您说 void 指针时,对于 C,它只是一个无意义的地址。它将 void 指针视为起始地址,并根据您提到的类型解释数据。
    【解决方案2】:

    编辑您的帖子非常不清楚。假设 data 实际上是一个指向 double 数组的指针,那么解决方案就更简单了:

    double * pd = static_cast<double const *>(data);
    double d0 = pd[0];
    double d1 = pd[1];
    

    或(C):

    double * pd= (double const *)(data);
    double d0 = pd[0];
    double d1 = pd[1];
    

    您无法对 void * 执行指针运算和取消引用,因此 *datadata + 8 无效。

    我不明白你到底想做什么,但这里是你如何访问数组中的数据:

    假设存储的数据实际上是int,要访问第8个元素并将其转换为double,你应该这样写:

    double el = static_cast<double>*(static_cast<int const *>(data) + 8));
    

    更好:

    int *p = static_cast<int const *>(data);
    double el = static_cast<double>(p[8]);
    

    请注意,将data 转换为原始指针类型非常重要。在我的示例中,我使用了 int,但您应该将其替换为您的实际数据。

    注意,如果您显示为 {0,0,0,0,0,0,0,40,20,0,0,0,0,0,0} 的内容实际上是字节,那么原始指针类型是 char *,您应该转换为 char *


    进一步澄清从指针转换数据:

    假设你有一个指向int的指针:

    int i  = 24;
    int *pi = &i;
    

    如何将地址pi 上的数据转换为双倍?

    // wrong:
    double *pd = &i;
    cout << *pd << endl;
    

    这是错误的,因为您所做的是转换指针类型而不是实际数据。实际上,您将地址pi 处的位模式解释为表示double 的位模式。但是那个位模式代表和int

    您需要做的是按原样检索数据:int,然后将int 转换为double

    int x = *pi;
    double d = (double) x;
    

    【讨论】:

    • 这是不正确的。如果您转换为另一种不同的 char 类型,并添加一些偏移量(例如您的 +8),编译器将跳转 8*sizeof(int) 个字节,这会将您引导到向量之外!从 void* 执行指针算术的正确转换总是通过 char* ,因此偏移量将以字节计算: double el = static_cast*(static_cast(data) + 8));
    • @LoPiTaL 如果数组中的数据是int 是正确的。那么一个元素是sizeof(int)字节长并且偏移量是正确的。
    • @LoPiTaL 因为 OP 只说 void * 然后显示类似 {0, 0, 8, 0} 我不知道元素是什么。如果他显示字节,那么是的,您应该转换为char *,但我的帖子仍然正确,因为数组的原始类型是char *,我明确声明他应该转换为原始类型。我使用int 作为占位符。
    • 好的,我删除了反对票,因为 OP 没有正确解释他的数据类型。无论如何,这些似乎都是字节,因为 0x4020000000000000 实际上是一个 8.0 值。
    • @LoPiTaL 是的,非常糟糕的问题。
    【解决方案3】:
    #include <stdio.h>
    #include <string.h>
    
    double myfunction(const void *data){
        double v;
        memcpy(&v, data, sizeof(v));
        return v;
    }
    int main (int argc, char *argv[]) {
        unsigned char data[] = {0x40,0x20,0,0,0,0,0,0};
        int i, len = sizeof(data);
    
        //reverse data If necessary
        for(i=0;i<len/2;++i){
            unsigned char c = data[i];
            data[i] = data[len -1 -i];
            data[len -1 -i] = c;
        }
        double v;
        v = myfunction(data);
        printf("%f\n", v);//8.000000
        return 0;
    }
    

    【讨论】:

    • 正如我在问题中提到的@BLUEPIXY,我想从 (40,20,0,0,0,0,0,0) 访问值,如何将它们自动存储在其他变量中,以及然后将 memcpy 用于其他变量将起作用.. 而且 i
    • @user3863496 需要颠倒数据的顺序,这取决于你要使用的机器的字节序。
    • 你能给我一些帮助吗,因为我收到的实际数据存储在 const void *data 是 {0,0,0,0,0,0,0,40,20,0,0, 0,0,0,0} 然后我将 {40,20,0,0,0,0,0,0} 中的值存储在一个数组中,假设 data1 现在我在反转 data1 的值时遇到问题反向调用 myfunction,因为现在我已经在 data1 中存储了值,并且我的函数有参数数据,所以当我调用 myfunction 时,它将调用数据而不是 data1。请在这方面帮助我,我该如何解决这个问题,我很困惑。 @BLUEPIXY
    • @user3863496 名称只会不同。
    【解决方案4】:

    您不能在 void 指针中执行指针运算,因为您不知道内部数据的大小(正如它所说,它是 void)。您必须将其类型转换为已知大小的类型。

    正确的类型转换和指针运算如下(使用旧的 C 转换):

    char * ptr=(char *)data;
    double * myDoublePtr=(double *)(ptr+8);
    double myDouble=*myDouble;
    

    或者,因为你有两个连续的双打:

    double * ptr=(double *)data;
    double myDouble=*(ptr+1); //This will access the second double.
    

    这是因为指针算术中的偏移量会执行偏移量*sizeof(type)字节的跳转,所以在char类型中,跳转的字节数实际上会和你的偏移量一样。

    【讨论】:

    • 我收到的数据是字节我希望这 8 个字节 40,20,0,0,0,0,0,0 加倍值 8.0 我尝试了你的建议但仍然有问题,因为当我分配第 8 个元素的地址,ptr 也将采用其他值来提供双精度类型结果,例如 (0x4020000000) 8.0。您能否提供一些建议.. 我想从第 8 个元素(即 40 到最后一个元素)访问,然后将整个八个元素转换为双精度值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多