приведение типа в с - PullRequest
       2

приведение типа в с

1 голос
/ 31 августа 2011

Я хотел бы знать, возможно ли получить тип, к которому я хотел бы привести динамически. Например,

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

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

Теперь я хочу знать, могу ли я набрать ptr, чтобы напечатать некоторые или некоторые_другие.

Я хочу точно знать, возможно ли иметь макрос, TYPE_CAST(comdition), который дает мне тип, показанный ниже:

(TYPE_CAST(condition)) ptr->common_field

должно быть эквивалентно

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

на основе condition

Следующее не работает, просто давая это, чтобы было легче понять c, чем английский:

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

Может ли что-то в этом духе быть сделано.

Спасибо.

Ответы [ 3 ]

2 голосов
/ 31 августа 2011

Это почти невозможно.Тип выражения определяется во время компиляции;это не может зависеть от каких-либо условий времени выполнения.

Вы можете, если известно, что void* указывает на объект одного типа или другого, сделать что-то подобное (я не проверял это):

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

Обратите внимание, что часть выражения ->common_field должна быть повторена;компилятор должен знать тип левого операнда оператора ->.

(В зависимости от контекста оператор if / else может быть более понятным.)

1 голос
/ 31 августа 2011

Способом проектирования структур данных, чтобы избежать вашей проблемы, может быть:

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

Тогда вы можете легко получить доступ к общему члену с помощью ptr->common_field независимо от того, какой из двух вариантов у вас есть. Я полагаю, что значение этого общего поля скажет вам, какого из двух членов союза вам нужно использовать для доступа к оставшимся членам, к которым вы затем получите доступ как ptr->some.member1 или ptr->some_other.member2.

0 голосов
/ 31 августа 2011

C90 не поддерживает это напрямую

Я предполагаю, что вы хотите написать какой-нибудь общий список в c90.Вот некоторые фрагменты, которые я использую в общем списке моего c90:

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

, используя его, вы можете получить доступ к содержимому при его вызове и всегда получить обратно тип Rigth.Вот несколько примеров:

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

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

явно отсутствуют некоторые части, но я хочу отметить, что NODEVALA, NODEVALB и NODEVALC имеют любой тип, который вы хотите, чтобы они имели, и список сохраняет их в формеуказателя void.

в вашем случае это можно сделать с помощью рекурсивных вызовов во время выполнения

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

}

В C90 нет способа использовать компилятор для таких вещей автоматически.Для этого вам понадобится полиморфизм, и это будет C ++ или лучше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...