This relates to C.
I am wondering if I can dynamically cast a pointer.
I have a struct called Value
that encapsulates different data (for example, int and float arrays):
typedef struct {
uint64_t count; // array length
int8_t type; // array type
uint8_t data[]; // array
} *Value;
ints have type = 1. floats have type = 2. (More types - including negative types - exist but are omitted in this example for simplicity.)
data[] can contain different types. The values are accessed by casting data, eg ((int *)x->data)[0]
.
Here is the code I use to add 2 Value
s:
#define ADD(x, y) ((x) + (y))
#define APPLY_OP(op) \
if (1 == ret->type){ \
APPLY_OP_ACCESSORS(op, ((int *)ret->data)); \
} \
else { \
APPLY_OP_ACCESSORS(op, ((float *)ret->data)); \
}
#define APPLY_OP_ACCESSORS(op, ra)
if (1 == x->type && 1 == y->type) { APPLY_OP_ITER(op, ra, ((int* )x->data), ((int* )y->data)) } \
else if (1 == x->type && 2 == y->type) { APPLY_OP_ITER(op, ra, ((int* )x->data), ((float*)y->data)) } \
else if (2 == x->type && 1 == y->type) { APPLY_OP_ITER(op, ra, ((float*)x->data), ((int* )y->data)) } \
else if (2 == x->type && 2 == y->type) { APPLY_OP_ITER(op, ra, ((floar*)x->data), ((float*)x->data)) }
#define APPLY_OP_ITER(op, ra, xa, ya) /* op, return/x/y accessors */ \
if (x->count == y->count) for (uint64_t i = 0; i < x->count; ++i) ra[i] = op( xa[i], ya[i] ); \
else if (x->count > y->count) for (uint64_t i = 0; i < x->count; ++i) ra[i] = op( xa[i], ya[0] ); \
else { for (uint64_t i = 0; i < y->count; ++i) ra[i] = op( xa[0], ya[i] );}
Value add(Value x, Value y){
// allocate an object for the return value
Value ret = getReturnObject(x, y);
// ...
// handle if error
// ...
// calculate
APPLY_OP(ADD);
return ret;
}
The APPLY_OP
macro has 2 branches, each having the same code except for the pointer type to the ret->data
struct member. Is there some way i can avoid this branching/duplication, and dynamically change the ret->data
pointer type instead? With more Value->type
s and more functions (subtract, multiply, divide, etc) the generated binary bloats up significantly.
NB this is simplified significantly from my own project. I omitted what I could. Hopefully the question is clear.