Passing a double as (void *) to a function - c

I wrote a function that receives a void * type argument and the plan that I can pass char* and int and in the receiving function I read whatever I expect.
It looks like:
void __declspec(dllexport) void* func(void *);
Next i tried to pass a double here:
double d = 3.14;
(*funcPtr)( (void *)d );
but got an error:
error: invalid cast from type 'double' to type 'void*'
Then I gone through method to pass double to void argument thread and tried this way:
double d = 3.14;
double *p_d = (double *)d;
(*funcPtr)( (void *)p_d );
But still the same luck:
error: invalid cast from type 'double' to type 'double*'
What am I missing and how to resolve my problem? I thought a solution would be to define several typedef of function pointers.

double d = 3.14;
double *p_d = &d;
You don't cast from a type to a pointer you need to reference it.
When you need to use the value in the pointer you dereference it like so.
double new_d = *p_d;
And inside a function that receives p_d as a void pointer, you'll have to cast the pointer back to a double pointer before use.
Like
void func(void *p_d)
{
double new_d = *(double*)p_d;
...
}

You have two general ways of doing this:
Get a pointer to either the double instance itself, or to a wrapper that holds it. Depending on how you call this thing, this may easily lead to an access violation if the value is held on the stack and your function ends before the called function uses the pointer.
double val;
fn(&val);
On a 64-bit system, if you're sure enough in your pointer-fu, you can store it as the pointer itself. Make sure you do the reverse in the called function, it won't be a pointer, it will be the double data itself.
double v;
fn((void *)(*(long long *)&v));

Similarly to what Blindy suggested it his option 2, I wanted to offer:
double d = 3.14;
void* p;
int id = sizeof d;
int ip = sizeof p;
//p = (void*)d;
memcpy(&p, &d, id);
If NoOb is dealing with a third-party library (judging by __declspec(dllexport)), he may not have a freedom to change interface.
Also, you should not be passing pointers to a library, as you don't know when is it safe to free it (and you can't delegate freeing to the library either).
A void* in C was used as universal storage for ages. If you can make sure that it has enough bits, and you know that the library is not going to derefernce it - just do it.

Related

Wrong value with a function that returns a double (libffi)

It seems that a function returning a double data type, from libffi, is not correctly casted when the function returns its value, here is the code I used:
#include <stdio.h>
#include <stdlib.h>
#include <ffi.h>
#include <math.h> // The make call the function `cos` by the FFI.
int main()
{
ffi_cif cif;
ffi_type *args[1];
void *values[1];
ffi_arg rc;
args[0] = &ffi_type_double;
void *ptr = malloc(sizeof(double));
*((double *)ptr) = 3.0;
values[0] = ptr;
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, 1, &ffi_type_double, args) == FFI_OK)
ffi_call(&cif, cos, &rc, values);
printf("%f\n", (double)rc);
return 0;
}
The result is as follows: 13830464316077631000.000000.
The ffi_arg type is an alias for unsigned long long. The documentation states that the argument of type ffi_arg passed to the ffi_call function, is used to store data if it is smaller than sizeof(ffi_arg), otherwise it is a pointer to the data in memory:
rvalue must point to storage that is sizeof(ffi_arg) or larger for
non-floating point types. For smaller-sized return value types, the
ffi_arg or ffi_sarg integral type must be used to hold the return
value.
(https://manpages.debian.org/testing/libffi-dev/ffi_call.3.en.html)
So I tried it with a pointer dereference:
void* rc;
// The code to call the function and initialize the CIF...
double my_value = *(double *)((void *)rc);
Which crashed the program.
How am I supposed to access the value stored using the rc variable?
EDIT 1
The command line used to compile the program:
gcc source.c -lffi -o source
There are no errors or warnings at compile time.
EDIT 2
After adding the `-Wall' build option, I get:
warning: passing argument 2 of 'ffi_call' from incompatible pointer type [-Wincompatible-pointer-types]
ffi_call(&cif, cos, &rc, values);
^~~
This warning seems to be ignored in the libffi example. The example given works very well for me (with this warning).
The problem is simple. The ffi_arg is not the type you're supposed to put your return value to. Instead, the 3rd argument is defined as a pointer to void, that should point to an object that is suitably large to contain the return value, and of proper alignment, and of proper type, or interpreted as such, thus:
double rv;
...
ffi_call(&cif, cos, &rv, values);
or
void *rv = malloc(sizeof (double));
...
ffi_call(&cif, cos, rv, values);
double value = *(double *)rv;
As for the warning, that happens because the libffi code is not strictly portable. A function pointer cannot be automatically converted to a void *. You can silence the warning with an explicit cast:
ffi_call(&cif, (void *)cos, rv, values);
At least it does not make it any more wrong than it already is.
EDIT -
According to the documentation
FFI -
rvalue must point to storage that is sizeof(ffi_arg) or larger for non-floating point types. For smaller-sized return value types, the ffi_arg or ffi_sarg integral type must be used to hold the return value.
The function definition for ffi_call is
void ffi_call(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue);
Instead of passing a ffi_arg to the function you need to pass a void* which is allocated space of a double.
void* rc = malloc(sizeof(double));
ffi_call(&cif, cos, rc, values);
printf("%f\n", *(double *)rc);
This will lead to a correct answer without you making any assumption about the function being called.

C: Passing array to pointer function

I'm not sure if the question has asked before, but I couldn't find any similar topics.
I'm struggeling with the following piece of code. The idea is to extend r any time later on without writing lots of if-else statements. The functions (func1, func2...) either take zero or one arguments.
void func1() {
puts("func1");
}
void func2(char *arg){
puts("func2");
printf("with arg %s\n", arg);
}
struct fcall {
char name[16];
void (*pfunc)();
};
int main() {
const struct fcall r[] = {
{"F1", func1},
{"F2", func2}
};
char param[] = "someval";
size_t nfunc = RSIZE(r); /* array size */
for(;nfunc-->0;) {
r[nfunc].pfunc(param);
}
return 0;
}
The code above assumes that all functions take the string argument, which is not the case. The prototype for the pointer function is declared without any datatype to prevent the incompatible pointer type warning.
Passing arguments to functions that do not take any parameters usually results in too few arguments. But in this case the compiler doesn't 'see' this ahead, which also let me to believe that no optimization is done to exclude these unused addresses from being pushed onto the stack. (I haven't looked at the actual assemble code).
It feels wrong someway and that's usually a recipe for buffer overflows or undefined behaviour. Would it be better to call functions without parameters separately? If so, how much damage could this do?
The way to do it is typedef a function with 1 argument, so the compiler could verify if you pass the correct number of arguments and that you do not pass something absolutely incompatible (e.g. a struct by value). And when you initialize your array, use this typedef to cast function types.
void func1(void) { ... }
void func2(char *arg) { ... }
void func3(int arg) { ... }
typedef uintptr_t param_t;
typedef void (*func_t)(param_t);
struct fcall {
char name[16];
func_t pfunc;
};
const struct fcall r[] = {
{"F1", (func_t) func1},
{"F2", (func_t) func2}
{"F3", (func_t) func3}
};
...
r[0].pfunc((param_t) "foo");
r[1].pfunc((param_t) "bar");
r[2].pfunc((param_t) 1000);
Here param_t is defined as uintpr_t. This is an integer type big enough to store a pointer value. For details see here: What is uintptr_t data type.
The caveat is that the calling conventions for param_t should be compatible with the function arguments you use. This is normally true for all integer and pointer types. The following sample is going to work, all the type conversions are compatible with each other in terms of calling conventions:
// No problem here.
void ptr_func(struct my_struct *ptr) {
...
}
...
struct my_struct struct_x;
((func_t) &ptr_func)((param_t) &struct_x);
But if you are going to pass a float or double argument, then it might not work as expected.
// There might be a problem here. Depending on the calling
// conventions the value might contain a complete garbage,
// as it might be taken from a floating point register that
// was not set on the call site.
void float_func(float value) {
...
}
...
float x = 1.0;
((func_t) &float_func)((param_t) x);
In this case you might need to define a function like this:
// Problem fixed, but only partially. Instead of garbage
// there might be rounding error after the conversions.
void float_func(param_t param) {
float value = (float) param;
...
}
...
float x = 1.234;
((func_t) &float_func)((param_t) x);
The float is first being converted to an integer type and then back. As a result the value might be rounded. An obvious solution would be to take an address of x and pass it to modified a function float_func2(float *value_ptr). The function would dereference its pointer argument and get the actual float value.
But, of course, being hardcore C-programmers we do not want to be obvious, so we are going to resort to some ugly trickery.
// Problem fixed the true C-programmer way.
void float_func(param_t param) {
float value = *((float *) &param);
...
}
...
float x = 1.234;
((func_t) &float_func)(*((param_t *) &x));
The difference of this sample compared to passing a pointer to float, is that on the architecture (like x86-64) where parameters are passed on registers rather than on the stack, a smart enough compiler can make float_func do its job using registers only, without the need to load the parameter from the memory.
One option is for all the functions accept a char * argument, and your calling code to always pass one. The functions that don't need an argument need not use the argument they receive.
To be clean (and avoid undefined behaviour), if you must have some functions that accept no argument and some functions that accept an argument, use two lists and register/call each type of function separately.
If the behaviour is undefined there's no telling how much damage could be caused.
It might blow up the planet. Or it might not.
So just don't do it, OK?

incompatible pointer type in C

so I'm trying to pass a type double * to a function that accepts void ** as one of the parameters. This is the warning that I am getting.
incompatible pointer type passing 'double **' to parameter of type 'void **'
Here is a snippet of my code.
int main( void )
{
// Local Declaration
double *target;
// Statement
success = dequeue(queueIn, &target);
}
Here's the prototype declaration of the function.
int dequeue ( QUEUE *queue, void **dataOutPtr );
I thought that if I passed target as a two level pointer that it would work, but I guess I'm wrong. Can someone please explain to me how come i'm getting this warning?
Even though all other pointer types can be converted to and from void * without loss of information, the same is not true of void ** and other pointer-to-pointer types; if you dereference a void ** pointer, it needs to be pointing at a genuine void * object1.
In this case, presuming that dequeue() is returning a single pointer value by storing it through the provided pointer, to be formally correct you would need to do:
int main( void )
{
void *p;
double *target;
success = dequeue(queueIn, &p);
target = p;
When you write it like this, the conversion from void * to double * is explicit, which allows the compiler to do any magic that's necessary (even though in the overwhelmingly common case, there's no magic at all).
1. ...or a char *, unsigned char * or signed char * object, because there's a special rule for those.
In your prototype declaration , you said second argument as void** ,so you have to type cast double** to void**.
Instead of this line success = dequeue(queueIn, &target);.
Call like this success = dequeue(queueIn,(void**) &target);
int main( void )
{
// Local Declaration
double *target;
// Statement
success = dequeue(queueIn, (void**)&target);
}
Use it like this.

Double pointer conversions, passing into function with `const void **ptr` parameter

GCC gives me folowing warning:
note: expected 'const void **' but argument is of type 'const struct auth **
Is there any case, where it could cause problems?
Bigger snippet is
struct auth *current;
gl_list_iterator_next(&it, &current, NULL);
Function just stores in current some void * pointer.
The error message is clear enough: you are passing a struct auth ** where a void ** was accepted. There is no implicit conversion between these types as a void* may not have the same size and alignment as other pointer types.
The solution is to use an intermediate void*:
void *current_void;
struct auth *current;
gl_list_iterator_next(&it, &current_void, NULL);
current = current_void;
EDIT: to address the comments below, here's an example of why this is necessary. Suppose you're on a platform where sizeof(struct auth*) == sizeof(short) == 2, while sizeof(void*) == sizeof(long) == 4; that's allowed by the C standard and platforms with varying pointer sizes actually exist. Then the OP's code would be similar to doing
short current;
long *p = (long *)(&current); // cast added, similar to casting to void**
// now call a function that does writes to *p, as in
*p = 0xDEADBEEF; // undefined behavior!
However, this program too can be made to work by introducing an intermediate long (although the result may only be meaningful when the long's value is small enough to store in a short).
Hm... I think constructs like const void * doesn't makes much sense.
Because if user wants to access data under void * he needs casting from void, and this action bypasses compiler type checks and consequently - constantness.
Consider this example:
#include <stdio.h>
#include <stdlib.h>
int main () {
int i = 6;
int * pi = &i;
const void * pcv = pi;
const int * pci = pi;
// casting avoids type checker, so constantness is irrelevant here
*(int *)pcv = 7;
// here we don't need casting, and thus compiler is able to guard read-only data
*pci = 7;
return 0;
}
So conclusion is that we need either void pointer Or to ensure constantness of data, but not both.

generic programming in C with void pointer

Even though it is possible to write generic code in C using void pointer(generic pointer), I find that it is quite difficult to debug the code since void pointer can take any pointer type without warning from compiler.
(e.g function foo() take void pointer which is supposed to be pointer to struct, but compiler won't complain if char array is passed.)
What kind of approach/strategy do you all use when using void pointer in C?
The solution is not to use void* unless you really, really have to. The places where a void pointer is actually required are very small: parameters to thread functions, and a handful of others places where you need to pass implementation-specific data through a generic function. In every case, the code that accepts the void* parameter should only accept one data type passed via the void pointer, and the type should be documented in comments and slavishly obeyed by all callers.
This might help:
comp.lang.c FAQ list ยท Question 4.9
Q: Suppose I want to write a function that takes a generic pointer as an argument and I want to simulate passing it by reference. Can I give the formal parameter type void **, and do something like this?
void f(void **);
double *dp;
f((void **)&dp);
A: Not portably. Code like this may work and is sometimes recommended, but it relies on all pointer types having the same internal representation (which is common, but not universal; see question 5.17).
There is no generic pointer-to-pointer type in C. void * acts as a generic pointer only because conversions (if necessary) are applied automatically when other pointer types are assigned to and from void * 's; these conversions cannot be performed if an attempt is made to indirect upon a void ** value which points at a pointer type other than void *. When you make use of a void ** pointer value (for instance, when you use the * operator to access the void * value to which the void ** points), the compiler has no way of knowing whether that void * value was once converted from some other pointer type. It must assume that it is nothing more than a void *; it cannot perform any implicit conversions.
In other words, any void ** value you play with must be the address of an actual void * value somewhere; casts like (void **)&dp, though they may shut the compiler up, are nonportable (and may not even do what you want; see also question 13.9). If the pointer that the void ** points to is not a void *, and if it has a different size or representation than a void *, then the compiler isn't going to be able to access it correctly.
To make the code fragment above work, you'd have to use an intermediate void * variable:
double *dp;
void *vp = dp;
f(&vp);
dp = vp;
The assignments to and from vp give the compiler the opportunity to perform any conversions, if necessary.
Again, the discussion so far assumes that different pointer types might have different sizes or representations, which is rare today, but not unheard of. To appreciate the problem with void ** more clearly, compare the situation to an analogous one involving, say, types int and double, which probably have different sizes and certainly have different representations. If we have a function
void incme(double *p)
{
*p += 1;
}
then we can do something like
int i = 1;
double d = i;
incme(&d);
i = d;
and i will be incremented by 1. (This is analogous to the correct void ** code involving the auxiliary vp.) If, on the other hand, we were to attempt something like
int i = 1;
incme((double *)&i); /* WRONG */
(this code is analogous to the fragment in the question), it would be highly unlikely to work.
Arya's solution can be changed a little to support a variable size:
#include <stdio.h>
#include <string.h>
void swap(void *vp1,void *vp2,int size)
{
char buf[size];
memcpy(buf,vp1,size);
memcpy(vp1,vp2,size);
memcpy(vp2,buf,size); //memcpy ->inbuilt function in std-c
}
int main()
{
int array1[] = {1, 2, 3};
int array2[] = {10, 20, 30};
swap(array1, array2, 3 * sizeof(int));
int i;
printf("array1: ");
for (i = 0; i < 3; i++)
printf(" %d", array1[i]);
printf("\n");
printf("array2: ");
for (i = 0; i < 3; i++)
printf(" %d", array2[i]);
printf("\n");
return 0;
}
The approach/strategy is to minimize use of void* pointers. They are needed in specific cases. If you really need to pass void* you should pass size of pointer's target also.
This generic swap function will help you a lot in understanding generic void *
#include<stdio.h>
void swap(void *vp1,void *vp2,int size)
{
char buf[100];
memcpy(buf,vp1,size);
memcpy(vp1,vp2,size);
memcpy(vp2,buf,size); //memcpy ->inbuilt function in std-c
}
int main()
{
int a=2,b=3;
float d=5,e=7;
swap(&a,&b,sizeof(int));
swap(&d,&e,sizeof(float));
printf("%d %d %.0f %.0f\n",a,b,d,e);
return 0;
}
We all know that the C typesystem is basically crap, but try to not do that... You still have some options to deal with generic types: unions and opaque pointers.
Anyway, if a generic function is taking a void pointer as a parameter, it shouldn't try to dereference it!.

Resources