Определение проблемы структуры в макросе - PullRequest
2 голосов
/ 23 марта 2011

Я работаю над макросами в C, пытаюсь смоделировать поведение объекта, но использую C, и у меня возникла проблема с определением переменной, определенной из структуры в другой структуре в макросе.Это мой код ... он работает:

#include <stdio.h>
#include <stdlib.h>

#define STACK_MAX_CAPACITY 10
#define DECLARE_STACK(Type)                             \
    typedef struct MetaPile_##Type;                     \
                                                        \
    typedef struct Pile_##Type_t{                       \
        Type q[STACK_MAX_CAPACITY];                     \
        int pos;                                        \
    } Pile_##Type;                                      \
                                                        \
    typedef struct MetaPile_##Type_t{                   \
        void (* push) ( Pile_##Type* p, Type val );     \
        void (*init) (Pile_##Type* p);                  \
    } MetaPile_##Type;                                  \
                                                        \
    void init_##Type( Pile_##Type* p ){                 \
        p->pos = 0;                                     \
        int i;                                          \
        for(i=0; i<STACK_MAX_CAPACITY; i++){            \
            p->q[i]=0;                                  \
        }                                               \
    }                                                   \
                                                        \
    void push_##Type( Pile_##Type* p, Type val ) {      \
        if(p->pos < STACK_MAX_CAPACITY){                \
            p->q[p->pos]=val;                           \
            p->pos++;                                   \
        }                                               \
    }                                                   \
    MetaPile_##Type TheMetaPile_##Type;                 \
    void initTheMetaPile_##Type(){                      \
        TheMetaPile_##Type.init = &init_##Type;         \
        TheMetaPile_##Type.push = &push_##Type;         \
    }                                                   \
                                                        \

DECLARE_STACK(int)

int main(){

    int i;

    initTheMetaPile_int();
    Pile_int pi;

    TheMetaPile_int.init(&pi);

    push_int(&pi, 2);
    push_int(&pi, 3);
    push_int(&pi, 4);
    push_int(&pi, 5);
    push_int(&pi, 6);

    for(i=0; i<STACK_MAX_CAPACITY; i++){
        printf("%d",pi.q[i]);
    }

    return 0;
}

Первая структура определяет массив динамического типа благодаря макросу (Pile _ ## Type), который представляет сторону атрибутов объекта и другую структуру(MetaPile _ ## Type), который будет управлять «методами» объекта с помощью указателей на функции.Fonction init работает как конструктор и инициализирует мой "objet" pi.

Теперь мне нужно иметь ссылку в Pile _ ## Тип переменной типа MetaPile _ ## Type (вызывается для примера myClass), чтобы можно было сделать pi-> myClass-> push ивызовите функцию push_int.Но когда я делаю:

typedef struct Pile_##Type_t{                       \
    Type q[STACK_MAX_CAPACITY];                     \
    int pos;                                        \
    MetaPile_##Type myClass;                        \
} Pile_##Type;                                      \

Я ошибочно понимаю ...

D:\main.c|40|warning: useless keyword or type name in empty declaration|
D:\main.c|40|error: syntax error before "MetaPile_int"|
D:\main.c|40|warning: no semicolon at end of struct or union|
D:\main.c|40|warning: type defaults to `int' in declaration of `Pile_int'|
D:\main.c|40|warning: data definition has no type or storage class|
D:\main.c|40|error: syntax error before '*' token|
D:\main.c|40|error: syntax error before '*' token|
D:\main.c|40|error: syntax error before '*' token|
D:\main.c||In function `init_int':|
D:\main.c|40|error: `p' undeclared (first use in this function)|
D:\main.c|40|error: (Each undeclared identifier is reported only once|
D:\main.c|40|error: for each function it appears in.)|
D:\main.c|40|error: syntax error before '*' token|
D:\main.c||In function `push_int':|
D:\main.c|40|error: `p' undeclared (first use in this function)|
D:\main.c|40|error: `val' undeclared (first use in this function)|
D:\main.c||In function `main':|
D:\main.c|47|error: syntax error before "pi"|
D:\main.c|49|error: `pi' undeclared (first use in this function)|
||=== Build finished: 12 errors, 4 warnings ===|

Я не знаю, что не так с определением myClass, я также использовал *но ошибка сохраняется.Спасибо, если кто-то может помочь.

Ответы [ 3 ]

4 голосов
/ 23 марта 2011

Ваша проблема не в использовании макросов, это только отвлекает вас.

typedef struct MetaPile_int;

просто синтаксически неверно. Простое предварительное объявление struct выглядит следующим образом:

struct MetaPile_int;

Но если вы просто хотите облегчить свою жизнь, сделайте это так:

typedef struct MetaPile_int MetaPile_int;

Это предварительное объявление struct и определение идентификатора MetaPile_int одновременно.

Чтобы все заработало, сначала попробуйте, не помещая в макрос. Или используйте компилятор, который поможет вам отслеживать ошибки в макросах, такие как clang.

2 голосов
/ 23 марта 2011

Удалить строку typedef struct MetaPile_##Type; - что это должно делать (кроме причинения ваших ошибок, то есть)?

0 голосов
/ 23 марта 2011

Вы пытаетесь вставить полную структуру (MetaPile_##Type) перед ее объявлением, измените их порядок следующим образом [в MetaPile_##Type вы используете только указатели на Pile_##Type_t, а размер указателей известен]: Редактировать: Это объявление прекрасно работает для меня:

#define DECLARE_STACK(Type)                             \
    struct Pile_##Type_t;                     \
                                                        \
    typedef struct MetaPile_##Type_t{                   \
        void (* push) ( Pile_##Type_t* p, Type val );     \
        void (*init) (Pile_##Type_t* p);                  \
    } MetaPile_##Type;                                  \
                                                        \
    typedef struct Pile_##Type_t{                       \
        Type q[STACK_MAX_CAPACITY];                     \
        int pos;                                        \
    MetaPile_##Type myClass;                        \
    } Pile_##Type;                                      \
                                                        \
    void init_##Type( Pile_##Type* p ){                 \
        p->pos = 0;                                     \
        int i;                                          \
        for(i=0; i<STACK_MAX_CAPACITY; i++){            \
            p->q[i]=0;                                  \
        }                                               \
    }                                                   \
                                                        \
    void push_##Type( Pile_##Type* p, Type val ) {      \
        if(p->pos < STACK_MAX_CAPACITY){                \
            p->q[p->pos]=val;                           \
            p->pos++;                                   \
        }                                               \
    }                                                   \
    MetaPile_##Type TheMetaPile_##Type;                 \
    void initTheMetaPile_##Type(){                      \
        TheMetaPile_##Type.init = &init_##Type;         \
        TheMetaPile_##Type.push = &push_##Type;         \
    }                                                   \
                                                        \

, и оно должно работать.

...