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.
精彩评论