开发者

Problem definition of struct in Macro

I'm working on macros in C, trying to simulate the objet behavior but using C and I'm having a problem with the definition of a variable defined from a struct in another struct in a macro. That's my code... it works:

#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.pus开发者_开发问答h = &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;
}

The first structure define an array of a dinamic type thanks to the macro (Pile_##Type) that represents the attributs side of an objet, and another structure (MetaPile_##Type) that will manage the "methods" of the objet, via fonction pointers. The fonction init works as a constructor and initialises my "objet" pi.

Now what I want is to have a reference in Pile_##Type of a variable of type MetaPile_##Type (called for exemple myClass) in order to be able to make pi->myClass->push and call the fonction push_int. But when I make:

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

I have a misunderstandable mistake...

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 ===|

I don't know what's worong with the defintion of myClass, I've used * also but the error persits. Thanks if somebody can help.


Your problem is not the usage of macros, this only distracts you.

typedef struct MetaPile_int;

is just syntactically incorrect. A simple forward declaration of a struct looks like this:

struct MetaPile_int;

But if you just want to make your life easier do it like this:

typedef struct MetaPile_int MetaPile_int;

This is a forward declaration of the struct and a definition of the identifier MetaPile_int at the same time.

To get it working try it without putting it in a macro, first. Or use a compiler that helps you trace errors in macros such as clang.


Remove the typedef struct MetaPile_##Type; line - what's that supposed to do (besides causing your errors, that is)?


You try to insert a full struct (MetaPile_##Type) before declaring it, change the order of them like that [ in MetaPile_##Type you only use pointers to Pile_##Type_t, and the size of pointers is known]: Edit: This declaration works for me fine:

#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;         \
    }                                                   \
                                                        \

and it should do the work.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜