在普通 C 中,如何将 void 指针值分配给 double

In plain C, how to assign a void pointer value to a double

void foo(void* p) {
    double d = (double) p; // Doesn’t compile.
    printf(“%f\n”, d);
}

我需要的是能打电话

foo((void*) 13.0);

并打印 13.0。

备注

我需要这个来存储源节点和存储在 C 哈希映射中的任意节点之间的距离(双精度类型),该哈希映射在图形搜索中是“void*”通用的。参见 https://github.com/coderodde/BidirectionalDijkstra4Perl2

当规范通过 void * 提供数据时,您通常打算使用它的方式是为数据分配内存并将内存地址作为 void * .然后接收数据的软件将 void * 转换为指向适当类型的指针,并使用该指针访问内存中的数据。

因此,如果您只需要一个 double 值,您可以这样做:

double *p = malloc(sizeof *p);  // Allocate memory for the data.
if (!p)  // Guard against allocation failure.
{
    fprintf(stderr, "Error, unable to allocate memory.\n");
    exit(EXIT_FAILURE);
}
*p = 13.0;  // Store data in memory.
foo(p);     // Pass the address of the data to foo.

稍后,在给定数据地址的某些例程中,您将执行如下操作:

void MyCallBackRoutine(void *vp) // Might be "const void *" instead.
{
    double *p = vp;  // Convert to "double *".  Might need "const" with it.
    printf("The conveyed data is %g.\n", *p);
}

您还应该在不再需要时释放内存。

如果您需要的不仅仅是 double 或其他单个项目,您可以创建一个 struct 包含您需要的所有成员并将所有数据放入其中。

标准方法已由给出。

但是如果void *的大小不小于double的大小,则可以将double的表示存储在void *中。从那时起,除了将表示提取回 double 对象外,您不能将指针用于任何事情。这是演示它的示例代码:

#include <stdio.h>    
#include <assert.h>
#include <memory.h>

void foo(void* p) {
    double d;
    memcpy(&d, &p, sizeof(d));
    printf(" % f\n", d);
}

int main() {
    void* p;
    // ensure that the representation of a double can fit in a void *
    static_assert(sizeof(void*) >= sizeof(double), "sizeof(double) > sizeof(void *)");
    double d = 13.0;
    memcpy(&p, &d, sizeof(d));
    foo(p);
    return 0;
}

但是注意:这应该只用作处理遗留代码的变通方法。可移植性仅限于 double 的大小不大于 void * 大小的平台,这在 32 位平台上是错误的。在 32 位模式下编译以上代码会引发编译错误:

error ...: sizeof(double) > sizeof(void *)

你可以通过一点指针技巧来做到这一点

void foo(void *p)
{
    double d = *((double *) &p);

    printf("%f\n", d);
}

它的工作原理是获取指向 p 的指针并将其解引用为 double,因此您可以将 void * 转换为 double

但请注意,只有当 double 和 void * 在计算机上具有相同的 len 时它才有效,您的代码将是 运行
否则它无法工作,因为 the way double are stored in memory