Using void * in C in place of overloading? - c

My question here is I had seen code like this for a multithreading application:
void Thread( void* pParams )
{
int *milliseconds = (int *)pParams;
Sleep(milliseconds);
printf("Finished after %d milliseconds", milliseconds); //or something like that
}
This greatly took my interest, I knew malloc sends back a void pointer and you can cast it to what you want, does this mean that I can create a function that can accept any data type?
For example a function I wrote without testing:
void myfunc( void* param )
{
switch(sizeof(param)) {
case 1:
char *foo = (char *)param; break;
case 2:
short *foo = (short *)param; break;
case 4:
int *foo = (int *)param; break;
}
}
myfunc(3.1415);
myfunc(0);
myfunc('a');
I may be completely wrong, even if this does work is it horrible practise? Thanks.

yes, void * is great for the creation of generic functions. However, once you pass a pointer to a certain datatype to a function that takes a void * you lose all type information. One way to steer your program so it knows which type you passed in is to have a 2nd parameter of type enum which may have values such as INT, FLOAT, DOUBLE etc. etc.
#include <stdio.h>
typedef enum inputTypes
{
INT,
DOUBLE,
CHAR
} inType;
void myfunc(void*, inType);
int main(void)
{
int i = 42;
double d = 3.14;
char c = 'a';
myfunc(&i, INT);
myfunc(&d, DOUBLE);
myfunc(&c, CHAR);
return 0;
}
void myfunc(void* param, inType type)
{
switch(type) {
case INT:
printf("you passed in int %d\n", *((int *)param));
break;
case DOUBLE:
printf("you passed in double %lf\n", *((double *)param));
break;
case CHAR:
printf("you passed in char %c\n", *((char *)param));
break;
}
}
Output
you passed in int 42
you passed in double 3.140000
you passed in char a

Yes, it is possible to create a function that accepts multiple type, but that is not how you do it.
In your myfunc, sizeof(param) will always be the same: sizeof is determined at compile time, and will be the size of a pointer.
The reason it works for threads, it generally it is known by the coder what the pointer points to, at compile time, and all you need is a simple cast. If you don't know at compile time what the void * points to, you must pass it at runtime somehow.
The key with void *: You can only cast them back to whatever they were in the first place, and it is up to you to know what that is. A simple void * by itself cannot tell you what it is pointing to.

sizeof(param) will always return the size of a pointer, so presumably 8 if you are on a 64-bit system. This has nothing to do with what it's pointing to.

Doesn't work because sizeof(param) is trying to take the size of a pointer.

The size of a void* is completely dependent on the system and determined at compile time, not on what is actually contained within it.

Related

Which type to use for an arbitrary function pointer in C?

In short, my question is: does the C standard allow for an arbitrary function pointer type similar to void * being an arbitrary data pointer type?
It is common to define call-back function types with a void * parameter to pass on an arbitrary data package whose format is known to the call-back function, but not to the caller.
For example:
typedef void (* EventFunctionType)(void *data);
void RegisterEventFunction(EventFunctionType function, void *data);
An "EventFunction" can then be registered with a data pointer which will be passed to the function when it is called.
Now suppose we want to pass a function pointer to the call-back. The function could have any prototype which would be known to the specific call-back function, just like the arbitrary data structure above.
A void * cannot hold a function pointer, so which type could be used?
Note: An obvious solution to this problem would be to wrap the function pointer in a data structure with the correct function pointer type, but the question is if the function pointer could be passed on directly in a generic form which the call-back could then cast to a pointer with the correct prototype?
There are no function pointer type that works the same as/similar to to void-pointer.
But function pointers has another characteristic that can be used. It's already referenced in the answer linked in this question:
In the C11 draft standard N1570, 6.3.2.3 §8:
A pointer to a function of one type may be converted to a pointer to a function of another type and back again.
This mean that you can use any function pointer type as your "arbitrary function pointer type". It doesn't matter as long as you know how to get back to the real/original type (i.e. know the original type so that you can cast correctly).
For instance:
typedef void (*func_ptr_void)(void);
and then use func_ptr_void as your "arbitrary function pointer type".
But notice that unlike conversion between void* and other object pointer types, the conversion between function pointers will always require an explicit cast. The code example below shows this difference:
#include <stdio.h>
typedef void (*func_ptr_void)(void);
typedef int (*f_int)(int);
int bar(int n)
{
return n * n;
}
int test(func_ptr_void f, int y)
{
f_int fc = (f_int)f; // Explicit cast
return fc(y);
}
int foo(void* p)
{
int* pi = p; // Explicit cast not needed
return *pi;
}
int main(void)
{
int x = 42;
void* pv = &x; // Explicit cast not needed
printf("%d \n", foo(pv));
func_ptr_void fpv = (func_ptr_void)bar; // Explicit cast
printf("%d \n", test(fpv, 5));
return 0;
}
does the C standard allow for an arbitrary function pointer type similar to void * being an arbitrary data pointer type?
No. Two function pointers are only compatible if their return types and parameters (including qualifiers) match.
However, pointer conversions between any two function pointers by means of a cast are well-defined (6.3.2.3/8) as long as you don't invoke the function through the wrong pointer type. This means that you can use any function pointer type as a "generic function pointer" as long as you keep track of what function that pointer actually points at. Such as using an extra enum for that purpose.
Generally when using function pointers, we don't do that however, but instead define a common interface. For example like the callbacks to bsearch/qsort which use the form int (*)(const void*, const void*).
Here's an example of "keep track of type using enum", which is not something I particularly recommend but otherwise perfectly well-defined:
#include <stdio.h>
static int intfunc (int x)
{
printf("%d\n", x);
return x;
}
static double doublefunc (double x)
{
printf("%f\n", x);
return x;
}
typedef enum
{
INTFUNC,
DOUBLEFUNC
} functype_t;
typedef void generic_func_t (void);
typedef int int_func_t (int);
typedef int double_func_t (double);
typedef struct
{
generic_func_t* fptr;
functype_t type;
} func_t;
void func_call (const func_t* f)
{
switch(f->type)
{
case INTFUNC: ((int_func_t*)f->fptr ) (1); break;
case DOUBLEFUNC: ((double_func_t*)f->fptr) (1.0); break;
}
}
int main (void)
{
func_t f1 = { (generic_func_t*)intfunc, INTFUNC };
func_t f2 = { (generic_func_t*)doublefunc, DOUBLEFUNC };
func_call(&f1);
func_call(&f2);
}
That's "old school" C, but it is not recommended since it is clunky, brittle and not really type safe. In modern C programming we wouldn't write that kind of code however, but replace that whole mess with something like this:
#include <stdio.h>
static int intfunc (int x)
{
printf("%d\n", x);
return x;
}
static double doublefunc (double x)
{
printf("%f\n", x);
return x;
}
#define func_call(obj) \
_Generic((obj), \
int: intfunc, \
double: doublefunc) (obj) \
int main (void)
{
func_call(1);
func_call(1.0);
}

Declaring void pointers to push type handling downstream

Is it ever common to do something like the following:
void *x = (void *) "one";
void *y = (void *) 2;
void *z = (void *) NULL;
Instead of:
char * x = "one";
int y = 2;
My reason for asking this is the ability to call a function that can accept multiple types. For example, a concat of various elements like is available in javascript. It seems like in a way using (void *) is just a simple way to mean "any type".
No, because you can't dereference a void pointer: you have to know what type is being stored, rendering the idea useless.
What you might be looking for is a variant type.
enum type {
CHAR, INT, DOUBLE, STR
};
typedef struct {
union {
char c;
int i;
double d;
char *str;
};
enum type t;
} variant;
void displayGenericObjec(variant v)
{
switch (v.t) {
case CHAR:
putchar(v.c);
break;
case INT:
printf("%d", v.i);
break;
case DOUBLE:
printf("%f", v.d);
break;
case STR:
printf("%s", v.str);
break;
}
}
variant x;
x.t = INT;
x.i = 42;
displayGenericObject(x);
This isn't a very practical solution, but it works for trivial code that only needs a few types.
Usually, it is not a good idea to write functions that take any argument. As noted in the comments, you lose on the compiler provided type-checking.
However, there are some cases where you might want to consider this using 'void *', which are (usually) considered acceptable are: (1) varargs functions and (2) callback. Important to emphasize that it is better to consider alternative implementation, if possible.
varargs functions are functions like 'printf', 'scanf', etc, where the function can accept variable number of arguments, potentially of different types, and will usually use clues (or convention) from the first arguments to properly decode the remaining arguments.
Callback are other example, where the code will sometimes have to specify a function that will be called on event. Many frameworks will require the callback to match a predefined "typedef", where the code will later cast the arguments into the actual type. For example, the 'qsort' prototype require a 'compar' function, which is generically defined to take 'void *', where the actual function will cast the parameters to the actual type.
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
On historical note, the initial versions of "C" (sometimes call "K&R C") did allow functions to be defined without formal parameter list. Practical experience has proven this to be risky, non-productive. In those days, you could write function in header files like:
/* in file.h */
int foo() ;
/* in file.c */
int foo(a)
int a ;
{
}
/* in prog.c */
{
a(5,4,"x") ;
}

Can you printf value from a void * in C

Ok, I'm trying to do this, but it isn't working becuase I'm not dereferencing the pointer... is there a way to do it without making a switch statement for the type?
typedef struct
{
char *ascii_fmtstr;
int len;
int (*deserializer)(void *in, const char *ascii);
int (*serializer)(const void *in, char *ascii);
} FORMAT;
const FORMAT formats[]=
{
{"%d\n", 2/2} //Int
,{"%s\n", STRSIZE/2} //String
,{"%.4f\n", 4/2} //Float
,{"%lld", 4/2} //Long-Long
,{"%s\n", STRSIZE/2} //Time
};
typedef struct {
int fmtindex;
void * vp;
} JUNK;
float f = 5.0f;
int i=1;
char foo[]="bar";
JUNK j[] = {
{2, &f}
,{0, &i}
,{1, foo}};
void dump(void)
{
int i;
for(i=0;i<2;i++)
printf(formats[j[i].fmtindex].ascii_fmtstr, j[i].vp);
}
It seems like you're using void * as a cheap union. That's a pretty bad idea. I think you'll find unions in conjunction with enums and switches make this look so much neater, in C. You'll find the switch amongst the #ifdef SWITCH ... #else, and the switchless version amongst the #else ... #endif.
#include <stdio.h>
struct object {
enum type {
d=0,
s=1,
f=2,
lld=3,
time=4
} type;
union instance {
int d;
char *s;
float f;
long long lld;
char *time;
} instance;
};
#ifdef SWITCH
void print_object(struct object *o) {
switch (o->type) {
case d: printf("%d", o->instance.d); break;
case s: printf("%s", o->instance.s); break;
case f: printf("%f", o->instance.f); break;
case lld: printf("%lld", o->instance.lld); break;
case time: printf("%s", o->instance.time); break;
};
}
#else
void print_d(struct object *o);
void print_s(struct object *o);
void print_f(struct object *o);
void print_lld(struct object *o);
void print_time(struct object *o);
void print_object(struct object *o) {
void (*print_functions[])(struct object *) = {
[d] = print_d,
[s] = print_s,
[f] = print_f,
[lld] = print_lld,
[time] = print_time
};
print_functions[o->type](o);
}
void print_d(struct object *o) { printf("%d", o->instance.d); }
void print_s(struct object *o) { printf("%s", o->instance.s); }
void print_f(struct object *o) { printf("%f", o->instance.f); }
void print_lld(struct object *o) { printf("%lld", o->instance.lld); }
void print_time(struct object *o) { printf("%s", o->instance.time); }
#endif
int main(void) {
struct object o = { .type = d, /* type: int */
.instance = { .d = 42 } /* value: 42 */ };
print_object(&o);
return 0;
}
You can print the pointer itself with something like %p but, if you want to print what it points to, you need to tell it what it is:
printf ("%d", *((int*)myVoidPtr));
You're not allowed to dereference a void * simply because the compiler doesn't know what it points to.
Think about it this way : Any pointer simply points to a single memory location.But the type of the pointer determines how many bytes after that to interpret/consider.If it is char* then (depending on system) 1 byte is interpreted,if it is an int* 4 bytes are interpreted, and so on.But a void* had no type.So you can't dereference a void pointer in C due to this simple reason.But you can print out the address it points to using the %p format specifier in printf() and passing that void pointer as argument.
printf("The address pointed by void pointer is %p",void_ptr); //Correct
printf("The address pointed by void pointer is %p",(void*)int_ptr);//Correct
assuming int_ptr is an integer pointer,say,and void_ptr is a void pointer.
printf("Value at address pointed by void pointer is %d",*void_ptr);// Wrong
printf("Value at address pointed by void pointer is %d",*(void*)int_ptr);//Wrong
It is not clear what your real goal is. Yes, there are ways to print data type dependent. Basically the idea is to create your own print function.
But only supplying the pointer will not be enough. In any case you need to supply pointer and the type of it.
Lets assume we have a function myprint:
myprint("%m %m %m %i", TYPE_INT, &i, TYPE_FLOAT, &f, TYPE_STRING, foo, 10);
would be a possible call. myprint is a varargs function then which needs to reconstruct the format string and arguments and then can call real printf.
If you use heap variables only, the type of the variable can be stored together with the data with some tricks (hint: check how malloc stores the block size). This would make the additional arguments superflous.
There are other solutions to that, but a good suggestion is not possible without knowledge of your real goal and the exact conditions.
I think the printf and its friends (fprintf, etc.) can dereference only char* which will be interpreted as a c-string.
Actually you can write such function yourself, because you will tell your function how to dereference void* with format flags.
Also you can add to the formats as a third value a pointer to required dereference function that will take as argument a void* and will return the value instead of pointer.
So you will need to write a function for each of the types you use in your formats and assign each function to each format properly.

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!.

Change string pointed by pointer

Many functions in c take pointer to constant strings/chars as parameters eg void foo(const char *ptr) . However I wish to change the string pointed by it (ptr).how to do it in c
You can just cast away the const:
void evil_function(const char *ptr)
{
char *modifiable = (char *) ptr;
*modifiable = 'f';
}
Note that this is dangerous, consider cases where the data being passed to the function really can't be changed. For instance, evil_function("bar"); might crash since the string literal is often placed in read-only memory.
Don't do it as it will cause your code to behave unpredictably. Basically the string pointed by const char* may be stored in the read-only section of your program's data and if you try to write something there, bad things will happen. Remember that foo can be called as foo("Test"), here you have not allocated memory for "Test" yourself, you just have a pointer to memory which contains the string. This memory may be read-only.
You can copy it to another piece of memory, and modify it there.
If you cast it to non-const, and then modify, chances are good you'll just segfault.
void foo(const char *x);
char data[4] = "Hi!";
int sum = 0;
for (int k=0; k<strlen(data); k++) {
foo(data); /* foo first */
sum += data[k];
}
printf("%d\n", sum);
Because foo() does not change its argument, the compiler can change this code to
void foo(const char *x);
char data[4] = "Hi!";
int sum = 0;
for (int k=0; k<strlen(data); k++) {
sum += data[k]; /* sum first */
foo(data);
}
printf("%d\n", sum);
But, if foo() changes the values in the data array, the results will be different according to the order the compiler chose to code the loop!
In short: don't lie to your compiler
How to lie to the compiler
Cast the const away
void foo(const char *readonly) {
char *writable = (char *)readonly;
/* now lie to the compiler all you like */
}
by notation "const char *ptr" we are telling Compiler
that ptr contains should not be changed.
Just, we can't change it!
The whole reason the const is so to express that the underlying content is not to be modified by this function, so don't change it because that will most likely break some code which is relying on the constness. other then that you can always cast the constness away using either const_cast<char*> or by directly casting the pointer
If you do it like this:
void dont_do_this_at_home(const char *ptr)
{
char **steve-o_ptr = (char **) &ptr;
char *bam_margera = "viva la bam";
*steve-o_ptr = bam_margera;
}
Then the pointer that you send into the function will be changed despite being a const pointer, the other suggestions so far only let you change the contents of the string, not the pointer to the string.
And I agree with the others that you shouldn't, ever, "un-const" any parameter you get, since the callee may really depend on that there are no side-effects to the function regarding those parameters.
There is also this way to get rid of the warnings/errors
typedef struct {
union {
const void* the_const;
void* the_no_const;
} unconsting;
}unconst_t;
/* Here be dragons */
void* unconst_pointer(const void* ptr) {
unconst_t unconst.unconsting.the_const = ptr;
return unconst.unconsting.the_no_const;
}
As you see it is quite possible and popular to actually do this, but you have to know what you are doing or mysterious faults may appear.

Resources