【问题标题】:Converting double to void* in C在 C 中将 double 转换为 void*
【发布时间】:2011-09-28 08:30:42
【问题描述】:

我正在编写一个解释器,我希望能够将函数返回的任何值存储到 void 指针中。我将整数和各种指针存储为 void 指针没有问题,但是在尝试将 double 类型转换为 void 指针时出现错误。我知道双精度的存储方式与位级别的整数和指针不同,但我不明白为什么我不能将我想要的任何位放入指针中(假设它已分配足够的内存)然后再将它们取出,将它们转换为双精度。

是否可以使用我不知道的语法将 double 转换为 void 指针,或者我误解了 void 指针的工作原理?

【问题讨论】:

标签: c void-pointers


【解决方案1】:

在许多系统上,double 的宽度为 8 字节,而指针的宽度为 4 字节。因此,前者不适合后者。

您似乎在滥用void*。您的解决方案将涉及分配至少与您需要以某种类似变体的结构存储的最大类型一样大的存储空间,例如union

【讨论】:

  • 我不敢相信我以前从未听说过工会。这正是我想要的。
【解决方案2】:

当然可以投射。空指针使 C 中的多态成为可能。您需要提前知道要传递给函数的内容。

void *p_v ;
double *p_d ;
p_d = malloc( sizeof( double ) ) ;
p_v = ( void * ) p_d ;

【讨论】:

  • 您的示例似乎有效,因为p_d 是一个指针。该操作询问有关 void* 转换的非指针。
【解决方案3】:

这里是

int main ( ) {
    double d = 1.00e+00 ; // 0x3ff0000000000000
    double * pd = & d ;
    void * * p = ( void * * ) pd ;
    void * dp = * p ;
    printf ( "%f %p %p %p \n" , d , pd , p , dp ) ;
    return 0 ;
} ;

输出

1.000000 0x7fff89a7de80 0x7fff89a7de80 0x3ff0000000000000

第二个和第三个地址可能不同。一条捷径

void * dp = * ( void * * ) & d ;

干杯

【讨论】:

  • 这是未定义的行为(严格的别名违规)
  • @M.M 不是。我正在投射指针,我知道我在做什么,它不是 c++,它编译并给出正确的输出。我不建议在长代码中使用这种技术,但我是对的。
  • 表达式 *p 的类型为 void * 但正在访问的内存实际上是 double * 类型的。这些甚至可能是不同的尺寸
  • 你是对的,我假设一切都是 64 位对齐的......否则你需要使用给定长度的 pchar 迭代读取
  • * ( void * * ) & d 是未定义的行为,它确实违反了严格的别名。
【解决方案4】:

继续法比奥。并确保您在 x64 上运行

int main()
{
    double d = 1.00e+00; // 0x3ff0000000000000
    double* pd = &d;
    void** p = (void**)pd;
    void* dp = *p;
    printf("%f %p %p %p \n", d, pd, p, dp);

    printf("%d %f\n", dp, *(double*)p);

    printf("%f\n", *(double*)(void **)&d);
}

输出

1.000000 0000000353F1FA30 0000000353F1FA30 3FF0000000000000
0 1.000000
1.000000

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-24
    • 1970-01-01
    • 2014-07-08
    • 2012-06-01
    • 2015-02-07
    • 2014-09-12
    • 2012-03-21
    相关资源
    最近更新 更多