void foo(void* p) {
double d = (double) p; // Doesn’t compile.
printf(“%f\n”, d);
}
What I need is to be able to call
foo((void*) 13.0);
and have 13.0 printed.
Note
I need this in order to store distances (of type double) between source nodes and arbitrary nodes stored in a C hash map that is “void*” generic in graph search. See https://github.com/coderodde/BidirectionalDijkstra4Perl2
CodePudding user response:
The standard way has been given by Eric's answer.
But if the size of a void *
is not smaller than the size of a double
, you can store the representation of the double
in a void *
. From that point you cannot use the pointer for anything but extracting back the representation to a double
object. Here is an example code demonstrating it:
#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;
}
But beware: this should only be used as a workaround to cope with legacy code. The portability is limited to platforms where the size of a double is not greater than the size of a void * which is false on a 32 bits platform. Compiling above code in 32 bits mode raises a compilation error:
error ...: sizeof(double) > sizeof(void *)
CodePudding user response:
When specification has a means of providing data through void *
, the way you are usually intended to use it is to allocate memory for the data and pass the address of the memory as a void *
. Then the software that receives the data converts the void *
to a pointer to the appropriate type and uses that pointer to access the data in memory.
Thus, if you just need a single double
value, a way you would do this is:
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.
Later, in some routine that was given the address of the data, you would do something like this:
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);
}
You should also free the memory when it is no longer needed.
If you need more than just a double
or other single item, you would create a struct
containing all the members you needed and put all the data into it.