If the type of a variable must be determined as runtime in C but the variable name is fixed and given, is there any way to reuse the code that involves the variable?
Actually I am asking about the C counterpart situation of runtime determine type for C++.
If possible please give some examples.
The C language does not have the object-oriented features that make it meaningful to ask about the run-time type of an object in C++.
You typically implement genericity in C by casting to and from void*
. Example: the C function qsort.
If your question is about determining at run-time what actual type a void*
pointer points to, that's impossible. The information is simply not stored at all by most compilers.
One standard technique is to provide a quick type info variable as a parameter and switch on that, and pass all data by reference. inside the function , we recover the value with explicit casting. The void* type is unchecked by the compiler so the danger is sending a type that is unhandled by the function (segmentation fault, data corruption or unknown behavior result). begin by setting up an enumeration of the types you need:
In this case I use the convention TYPE_FUNCTION to represent a function returning a type.
The enum directive chooses successive integers from 0, or you can assign each enumeration its own int value.
typedef enum D_types {
ANINT, // don't use actual system type names
AFLOAT,
ADOUBLE,
ASTRING,
MY_STRUCT=100,
MY_STRUCT2=200
VOID_FUNCTION=1000,
INT_FUNCTION = 2000,
STRUCT_FUNCTION=3000
} DATATYPE;
/* an f_int is a function pointer to a function */
typedef int (*f_int)(int, void* );
In your function definition you send both the data by reference and the type and cast it to the correct type before use:
int myfunction ( DATATYPE dt, void* data, )
{
int an_int = 0;
int * ip; // typed pointers for casting of the void pointer data
double * dp;
char * sp;
struct My_struct * msp;
struct My_struct_2 * ms2p;
f_int fp;
...
switch (dt){
case ANINT:
ip = (int*) data; // only pointers can be assigned void pointer values.
int i = *ip // dereference of typed pointer, no dereferencing void pointers.
...
break;
case ADOUBLE:
dp = (double*) data;
double d = *dp;
...
break;
case ASTRING:
char * s = strdup( (char*) data); // cast to char pointer allowed (pointer->pointer)
...
break;
case MY_STRUCT:
msp = ( struct My_Struct *) data;
char* ms_name = msp->name; // if my_struct has a name string ...
float dollarvalue = msp->dvalue;
...
case INT_FUNCTION:
fp = (f_int)data;
an_int = fp( ANINT, 5);
}
return an_int;
}
As you might guess, this is playing with matches in a fireworks factory, and not encouraged as a constant practice.
in your code you would call it like this:
double pi =3.14159;
int g = myfunction( ADOUBLE, &pi ); // pass by reference, not value
int j = myfunction (ASTRING , "HEY NOW" ); //C strings pass by ref normally
f_int myfunc = myfunction; // a function pointer (ref to the functions address )
int r = myfunction ( INT_FUNCTION, myfunc ); /* function as a parameter ... */
Other than for a one-off function it is recommend to use the varargs functions http://www.eskimo.com/~scs/cclass/int/sx11b.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With