Dave win wrote:
I'm confused with the expression "(float *())".
Book says that this is a cast. But, I have no idea of this expr.
why could this expr ignore the variable???
Sometimes you want to create something that doesn't know what it is
dealing with. You can just hand it some random data in void pointers
(that is, a pointer that officially just points to "some unknown
something, maybe") plus some extra info which tells you precisely what
that void* is supposed to point to.
For example in the below example, I keep an array of void pointers to
all of my math functions. Then I have an array of desired operations
which, in conjunction with the type of my datatype, I use to access the
array of math functions.
#define TYPE_INT 0
#define TYPE_FLOAT 1
struct genericNumber { /*a generic variable type that can pretend to be
any kind of number*/
int type; /*what type it should be interpretted as*/
int intVal;
float floatVal;
};
#define OP_ADD 0 /*possible operations*/
#define OP_SUB 1
int addInts(int a, int b) { /*a function for each operation and each
possible type of number*/
return a + b;
}
float addFloats(float a, float b) {
return a + b;
}
int subInts(int a, int b) {
return a - b;
}
float subFloats(float a, float b) {
return a - b;
}
void* funcs[] = {addInts, addFloats, subInts, subFloats}; /*keep them
in an array so that we can perform operations based on some sort of
script instead of hard coded functionality*/
int opCount = 5;
int ops[] = {OP_ADD, OP_ADD, OP_SUB, OP_ADD, OP_SUB}; /*operations we
want to perform and the order we want to perform them*/
int main(void) {
int L;
struct genericNumber a;
struct genericNumber b;
a.type = TYPE_INT;
a.intVal = 5;
b.type = TYPE_FLOAT;
b.floatVal = 3.0f;
/*run all operations, indexing into our function array based on
operation and variable type. Righthand parameter will be cast to be the
same as lefthand. The result of the operation will be written back into
the variable that was the lefthand parameter (a)*/
for (L = 0; L < opCount; L++) {
if (a.type == TYPE_INT) {
if (b.type == TYPE_INT) {
a.intVal = ((int (*)(int, int))funcs[ops[L] <<
1])(a.intVal, b.intVal); /*cast our void* to a function of the correct
type. We are assuming that all of our math is correct and that our
functions are similarly all in the right order in our function array*/
}
else if (b.type == TYPE_FLOAT) {
int temp = (int)b.floatVal;
a.intVal = ((int (*)(int, int))funcs[ops[L] <<
1])(a.intVal, temp);
}
}
else if (a.type == TYPE_FLOAT) {
if (b.type == TYPE_INT) {
float temp = (float)b.floatVal;
a.floatVal = ((float (*)(float, float))funcs[(ops[L] << 1])
+ 1)(a.floatVal, temp);
}
else if (b.type == TYPE_FLOAT) {
a.floatVal = ((float (*)(float, float))funcs[(ops[L] <<
1]) + 1)(a.floatVal, b.floatVal);
}
}
}
return 0;
}
This is the kind of thing I can imagine you might do if you were
building the engine for a scripting language that used generic variable
types. If you just assume that for every operation there will only be
two inputs and one output, then you would parse the script code and
create arrays of generic variables, lefthand and righthand parameters,
what variable to assign the result to, and what operation to perform.
Voila, Perl.
* note that I just wrote that code in there and have not tested, so no
guarantees that it works correctly.
-Chris