2013-03-08 4 views
3

У меня есть две разные структуры с определением типа поля (см. Ниже).дифференцируя структуру на основе типа

struct A { 
int type; 
char type_a[8]; 
char random[8]; 
}; 


struct B { 
int type; 
char type_b[16]; 
char random[16]; 
}; 

Теперь я хочу, чтобы различать эти две структуры на основе типа Так, например

if (type == A) 
struct A *a = (struct A *)buff; 
if (type == B) 
struct B *b = (struct B *)buff; 

Я не знаю, какой тип структуры передается мне нагишом перед рукой. Итак, как мне извлечь тип из buff. Поле типа гарантируется как первое поле в обеих структурах.

+1

вы имеете в виду положительный эффект будет пустота * – deeiip

+0

Не могли бы вы объяснить более подробно, что ваш intented использование ? – qPCR4vir

+0

Вот проект, который поможет http://www.cs.rit.edu/~ats/books/ooc.pdf –

ответ

0

Предполагая, что вы не хотите/не можете изменить А и В:

#define TYPE_A 0 
#define TYPE_B 1 

...

struct *B create_B() 
{ struct *B= malloc(sizeof B); 
    B->type=TYPE_B; 
    return B; 
} 

...

void *buff=create_B(); 

...

struct A a; 
a.type=TYPE_A; 
void *buff=&a; 

...

struct A *a=NULL; 
struct B *b=NULL; 
int type = *((int *)buff); 
if (type == TYPE_A) 
a = (struct A *)buff; 
else if (type == TYPE_B) 
    b = (struct B *)buff; 

Проблема с кодом является то, что объем а и Ь только внутри, если, и, возможно, вам это нужно больше.

+0

, здесь дело не в этом. Вопрос в том, может ли бафф-указатель распознаваться как struct A * или struct B *, если он передан как void * – deeiip

+0

@ me.deeiip Я предположил, что тип уже известен, как первый, который вы читали из файла, например. – qPCR4vir

3

Вы можете сделать этот тип вещей с шаблоном проектирования ООП в С.

Идеи заключается в том, что Base структуры имеет type элемент. Структуры A и B «удлинить» Base. Так как структура Base является первым элементом как A, так и B, либо может быть отлита до Base и использоваться как таковая.

Это даст вам безопасный способ бросить между Base и A или B, давая типобезопасность время компиляции, когда вам просто нужно использовать экземпляр Base.

typedef struct Base { 
    int type; 
} Base; 

typedef struct A { 
    Base base; 
} A; 

typedef struct B { 
    Base base; 
} B; 

int ATYPE = 1; 
int BTYPE = 2; 

int getType(Base *base) { 
    return base->type; 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    A a; 
    B b; 
    B *bptr; 
    Base *base; 
    int baseType; 

    a.base.type = ATYPE; 
    b.base.type = BTYPE; 

    base = (Base*)&b; 

    baseType = getType(base); 

    // something like this is reasonable, 
    // since you know that base is an 
    // instance of B. 
    if (baseType == BTYPE) { 
     bptr = (B*)base; 
    } 

    if (baseType != BTYPE) return -1; 
    return 0; 
} 
+1

Стоит отметить, что это верно, потому что стандарт гарантирует, что перед первым членом структуры не будет прокладки. – 2013-03-08 20:50:33

+0

@ H2CO3, что это единственное, что думает, что структура адреса сокета работает по-другому, каждая вещь становится зависимой от платформы. Вы дали ** очень важный пункт **. –

1

С имеет union функцию для структур данных, таких как это. Союз похож по внешнему виду на структуру, но каждый член в союзе занимает одно и то же место в памяти. Затем вы используете другое поле, type в приведенном ниже примере, чтобы вы могли узнать, как интерпретировать структуру.

Используя это, вы можете подойти к своей проблеме без какого-либо литья и сохранить безопасность типа компиляции.

Вот полный пример:

#include <stdio.h> 
#include <string.h> 

#define TYPE_A 1 
#define TYPE_B 2 

struct A 
{ 
    char member1[8]; 
    char member2[8]; 
}; 

struct B 
{ 
    char member1[16]; 
    char member2[16]; 
}; 

struct base 
{ 
    int type; 
    union 
    { 
     struct A a; 
     struct B b; 
    } data; 
}; 

char *get_member2(struct base *buff) 
{ 
    if (buff->type == TYPE_A) 
     return buff->data.a.member2; 

    if (buff->type == TYPE_B) 
     return buff->data.b.member2; 

    return NULL; 
} 

int main(void) 
{ 
    struct base b1; 
    struct base b2; 

    /* Set up test structs. */ 

    b1.type = TYPE_A; 
    strcpy(b1.data.a.member2, "Hello"); 

    b2.type = TYPE_B; 
    strcpy(b2.data.b.member2, "World"); 

    /* Print member2 from each struct. */ 

    printf("%s\n", get_member2(&b1)); 
    printf("%s\n", get_member2(&b2)); 

    return 0; 
} 

Выход:

Hello 
World 

code: Codepad

+0

Дон Хороший ответ! вы должны написать пример, чтобы продемонстрировать пользователя. ваш ответ лучше –

+0

OK - я внесла свой ответ, чтобы включить полный пример. –

+0

очень приятно! ..... \ –