2017-02-15 18 views
1

Пусть этот код в качестве примера:Macro, который знает, аннулируются * Тип распределения

typedef struct { 
    int value; 
    char another; 
} foo; 

typedef struct { 
    float yet_another; 
    long really_another; 
} bar; 

typedef struct { 
    char* name; 
    void* data; 
} gen; 

int main(int argc, char** argv) { 
    gen foo_gen, bar_gen; 

    foo_gen.name = "Foo"; 
    foo_gen.data = (foo*) malloc(sizeof(foo)); 

    bar_gen.name = "Bar"; 
    bar_gen.data = (bar*) malloc(sizeof(bar)); 

    ((foo*) foo_gen->data)->value = 0; 
    ((bar*) bar_gen->data)->yet_another = 1.0f; 

    return 0; 
} 

Этот код будет работать нормально, поэтому я определил 2 макросъемки, чтобы облегчить мою работу:

#define FOO_DATA(N, D) ((foo*) N->data)->D 
#define BAR_DATA(N, D) ((bar*) N->data)->D 

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

#define DATA(N, D) (__auto_type N->data)->D 

Но это не сработало. Кажется, что typeof не работает с макросами. Как я должен это делать?

+2

Из чего вы его отбрасываете, и что определяет, на что вы его набросили? – Ryan

+0

Где макрос должен получить информацию о том, какой тип 'data_s' должен быть? – user2357112

+0

Обратите внимание: это анти-шаблон. В c вы не должны указывать тип переменной. Вместо этого вы должны попробовать некоторые из хорошо известных методов, чтобы делать то, что похоже на общие типы, но это не так. Вы можете 1. Использовать объединение, 2. Использовать указатели 'void *'. Кроме того, ваш макрос полностью неясен, потому что 'self-> data' должен быть 1. Non-NULL и 2. Объявлено где-то в другом месте, поэтому макрос действительно не имеет смысла. –

ответ

3

Если я и другие комментаторам правильно понимаю, вы хотите быть в состоянии сделать что-то вроде этого:

struct a { 
    int field1; 
} a; 

struct b { 
    int field2; 
} b; 

void *self1 = &a; 
void *self2 = &b; 

int f1 = MAGIC(self1)->field1; 
int f2 = MAGIC(self2)->field2; 

для некоторого определения MAGIC.

Это не представляется возможным в С.

0

Расширение на мой комментарий: вы бы сгруппировать общие поля в другой структуры и сделать что первое поле из возможных структур в self->data:

struct common { 
    int foo; 
}; 

struct a { 
    struct common common; 
    int bar; 
}; 

struct b { 
    struct common common; 
    int baz; 
}; 

#define $(D) (((struct common*) self->data)->D)