简体   繁体   中英

typecasting in c

I would like to know if it is possible to get the type to which I would like to cast dynamically. For eg.

void *ptr;
typedef struct {
..
common_field;
..
} some;

typedef struct {
    ..
    common_field;
    ..
    } some_other;

Now I want to know if I can typecast ptr to type some or some_other dynamically.

precisely what I want to know is if it is possible to have a macro, TYPE_CAST(comdition) which gives me the type like shown below:

(TYPE_CAST(condition)) ptr->common_field

should be equivalent to

((some *) ptr)->common_field or ((some_other *) ptr)->common_field

based on the condition

The following doesn't work, just giving this so that it might be clear to understand c than english:

TYPE_CAST(condition) ((condition) ? (some *) : (some_other *))

Can something along these lines can be done.

Thanks.

That's pretty much not possible. The type of an expression is determined at compile time; it can't depend on any execution time condition.

You can, given a void* that you know points to an object of one type or the other, do something similar (I have not tested this):

condition ? ((some*)ptr)->common_field : ((some_other*)ptr)->common_field

Note that the ->common_field part of the expression has to be repeated; the compiler has to know the type of the left operand of the -> operator.

(Depending on the context, an if/else statement might be clearer.)

A way to design your data structures to avoid your problem could be:

typedef struct {
    int common_field;
    union {
        struct {
            int member1;
        } some;
        struct {
            char* member2;
        } some_other;
    };
} common_struct;
common_struct* ptr;

Then you can easily access the common member with ptr->common_field regardless of which of the two variants you have. I would imagine that the value of this common field will tell you which of the two members of the union you need to use to access the remaining members, which you will then access as ptr->some.member1 or ptr->some_other.member2 .

C90 does not support this directly

I assume you want to write a generic list of some sort in c90. Here are some snippets i use in a generic c90 list of mine:

typedef struct {
void *rigth;
void *left;
void *value;
int index;
}GENLIST_node;
#define GENLIST_getValuePtr(NODE, index, valptr) __GENLIST_getValuePtr ((NODE), (index), (void*)(valptr)) 

using this you can access the content when calling it and always get the rigth type back. Here are some examples:

int *NODEVALA = NULL;
double *NODEVALB = NULL;
char *NODEVALC = NULL;

GENLIST_getValuePtr(&AnyNode, -1, &NODEVALA);
GENLIST_getValuePtr(&AnyNode, -1, &NODEVALB);
GENLIST_getValuePtr(&AnyNode, -1, &NODEVALC);

there are obviousely some parts missing , but what i want to point out is that NODEVALA, NODEVALB and NODEVALC have whatever type you want them to have and the list saves them in form of a void pointer.

in your case this could be done with recursive calls during runtime

switch(condition){
    case condition_structA:
    structA *X;
    getValPtr(&X);
    ...
    break;
    structB *X;
    getValPtr(&X);
    ...
    case condition_structB:
    break;

}

In C90 there is no way the compiler can be used to do things like that automatically. To do this you would need polymorphism and that would be C++ or better.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM