在普通 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
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