defines and structure instantiation

R

Rich

Suppose the following:

typedef void (*funcptrs)(void);

typedef struct {
unsigned int *in;
unsigned int *out;
unsigned int *overrun;
funcptrs myptrs[1]; /* >=1 for ansi */
} yada;

Is it possible to write a #define in which I can vary the storage array
size? What I mean is suppose you had:

mystruc(10, name)
mystruc(20, name)

and a #define mystruc(A,B) ...

The A would set the size of the myptrs array and the B would be the name of
the declared structure. Perhaps a union might allow the define to create
the appropriate size array? The issues is that for the hardware I'm
targeting the unsigned int *s will be 2 bytes (point to RAM) and the void
(*)(void) will be 3 bytes (point to code space in flash). If they were
both two bytes it would be easier (at least for me!). Any good ideas on
this?

Thanks

PS: I cross posted this to the moderated forum inadvertantly...sorry!
 
R

Robert Gamble

Rich said:
Suppose the following:

typedef void (*funcptrs)(void);

typedef struct {
unsigned int *in;
unsigned int *out;
unsigned int *overrun;
funcptrs myptrs[1]; /* >=1 for ansi */
} yada;

Is it possible to write a #define in which I can vary the storage array
size? What I mean is suppose you had:

mystruc(10, name)
mystruc(20, name)

and a #define mystruc(A,B) ...

The A would set the size of the myptrs array and the B would be the name of
the declared structure.

#define mystruc(A, B) struct {\
unsigned int *in; \
unsigned int *out; \
unsigned int *overrun; \
funcptrs myptrs[A]; \
} B

mystruc(10, test);

Robert Gamble
 
R

Rich

Robert said:
#define mystruc(A, B) struct {\
unsigned int *in; \
unsigned int *out; \
unsigned int *overrun; \
funcptrs myptrs[A]; \
} B

mystruc(10, test);

Thanks! I'm still having some difficulty:

I have this in a header file:

#define mystruc(A,B) struct { \
unsigned int *in; \
unsigned int *out; \
unsigned int *overrun; \
funcptrs myptrs[A+1]; \
} B = {(unsigned int *)&B.funcptrs[0],(unsigned int *)&B.funcptrs[0]
(unsigned int *)&B.funcptrs[A]}

This is in code:
mystruc(10, myq);

Now, when I try to use myq as in the following:
myfunc((unsigned int *)myq);

where myfunc is defined as:
myfunc(unsigned int *qu){
Qtype *q = (Qtype *)qu;
q->remove = q->insert = (unsigned int *)&q->mem[0];
}
I receive errors about myq being unable to cast from an anonymous stuct to
unsinged int. I'm trying to create unsigned int pointers that store
pointers into RAM space where 3 byte function pointers are stored.

Thanks again.
 
R

Robert Gamble

Rich said:
Robert said:
#define mystruc(A, B) struct {\
unsigned int *in; \
unsigned int *out; \
unsigned int *overrun; \
funcptrs myptrs[A]; \
} B

mystruc(10, test);

Thanks! I'm still having some difficulty:

I have this in a header file:

#define mystruc(A,B) struct { \
unsigned int *in; \
unsigned int *out; \
unsigned int *overrun; \
funcptrs myptrs[A+1]; \
} B = {(unsigned int *)&B.funcptrs[0],(unsigned int *)&B.funcptrs[0]
(unsigned int *)&B.funcptrs[A]}

I'm not sure what you are trying to do in this last line, it doesn't
make much sense to me. It looks like you are trying to make the
initializer part of the macro but the structure doesn't have a member
named funcptrs and even if it did the initializer would be invalid
because it tries to initialize part of itself to parts that have not
been initialized yet. I would do the initialization seperately if I
were you.
This is in code:
mystruc(10, myq);

Now, when I try to use myq as in the following:
myfunc((unsigned int *)myq);

You are casting the value of the structure to a pointer which doesn't
make any sense, you probably want to cast the address of the structure:

myfunc((unsigned int *)&myq);
where myfunc is defined as:
myfunc(unsigned int *qu){
Qtype *q = (Qtype *)qu;
q->remove = q->insert = (unsigned int *)&q->mem[0];
}
I receive errors about myq being unable to cast from an anonymous stuct to
unsinged int.

I don't know what a Qtype is so that doesn't mean much to me. Instead
of summerizing the errors you get, just copy and paste the error
message itself. Making the change above should fix the error you
describe.

Robert Gamble
 
R

Robert Gamble

Robert said:
Rich said:
Robert said:
#define mystruc(A, B) struct {\
unsigned int *in; \
unsigned int *out; \
unsigned int *overrun; \
funcptrs myptrs[A]; \
} B

mystruc(10, test);

Thanks! I'm still having some difficulty:

I have this in a header file:

#define mystruc(A,B) struct { \
unsigned int *in; \
unsigned int *out; \
unsigned int *overrun; \
funcptrs myptrs[A+1]; \
} B = {(unsigned int *)&B.funcptrs[0],(unsigned int *)&B.funcptrs[0]
(unsigned int *)&B.funcptrs[A]}

I'm not sure what you are trying to do in this last line, it doesn't
make much sense to me. It looks like you are trying to make the
initializer part of the macro but the structure doesn't have a member
named funcptrs and even if it did the initializer would be invalid
because it tries to initialize part of itself to parts that have not
been initialized yet. I would do the initialization seperately if I
were you.

Ignore what I said in the second sentence. The reason it would not be
valid is because the address of the array elements is not available
during the initialization. Something like this should work:

#define mystruc(A, B) struct {\
unsigned int *in; \
unsigned int *out; \
unsigned int *overrun; \
funcptrs myptrs[A]; \
} B; B.in = B.out = (unsigned int *)&B.myptrs[0]; \
B.overrun = (unsigned int *)&B.myptrs[A];

Make sure you copy&paste your code instead of re-typing it as you
obviously did here (you were missing a comma in the initializer and the
member name is myptrs, not funcptrs which your compiler should have
caught). I assume that you can safely convert a function pointer to a
pointer to unsigned int on your platform, the ability to safely do this
is not guaranteed by the Standard.

Robert Gamble
 
C

Chris Torek

Assuming I got all the ">>>"s right:
Robert Gamble wrote:

#define mystruc(A, B) struct {\
unsigned int *in; \
unsigned int *out; \
unsigned int *overrun; \
funcptrs myptrs[A]; \
} B

mystruc(10, test);

Note that this creates an anonymous type, so the only thing
you can do with the object is work directly with it. (In
particular you cannot create a pointer that points to this
type, because you have no associated name.)

You can, however, apply the "struct hack" (or C99's flexible
arary member technique) with reasonable hope for portability.
Rich said:
Thanks! I'm still having some difficulty:

I have this in a header file:

#define mystruc(A,B) struct { \
unsigned int *in; \
unsigned int *out; \
unsigned int *overrun; \
funcptrs myptrs[A+1]; \
} B = {(unsigned int *)&B.funcptrs[0],(unsigned int *)&B.funcptrs[0]
(unsigned int *)&B.funcptrs[A]}

This is ... suspicious at best.

This is one of the big problems ...

but this is not: &B.funcptrs[0] would be valid (as an "address
value" for an initializer, which is not a constant but is a valid
initializer even for objects with static duration) provided that
"B" itself has static duration. (If "B" has automatic duration,
this is only valid in C99.)

That should only help if B has automatic duration and the compiler
only handles C89 (or C90 or C94) instead of C99.

A bigger problem, to me anyway, is the use of "unsigned int *".
"funcptrs" (which was snipped) is an alias for "void (*)(void)",
i.e., pointer to function (of no arguments) returning void.
If B is an object (of unname-able type) containing a member
of type "array N of (void (*)(void))", then &B.member has
type "pointer to (void (*)(void))" or "void (**)(void)":

#define DECLARE(n, typename, objectname) \
struct typename { \
void (**in)(void); \
void (**out)(void); \
void (**overrun)(void); \
void (*funcs[(n)+1])(void); \
} objectname = { \
&objectname.funcs[0], \
&objectname.funcs[0], \
&objectname.funcs[n] \
}

which now needs no casts. Of course you still need to fill
in the actual function pointer values.

Ignore what I said in the second sentence. The reason it would not be
valid is because the address of the array elements is not available
during the initialization.

Only true for objects with automatic duration, in which case the
entire brace-enclosed contents are not valid initializers for an
object with static duration -- but we just said that the object has
automatic duration! In C99, the brace-enclosed list becomes a
compound literal, which has a lot of latitude. (Only compound
literals that are outside functions require constant-expressions,
and if this declaration were outside a function, the object would
have static duration.)

[snippage]
Make sure you copy&paste your code instead of re-typing it as you
obviously did here (you were missing a comma in the initializer and the
member name is myptrs, not funcptrs which your compiler should have
caught). I assume that you can safely convert a function pointer to a
pointer to unsigned int on your platform, the ability to safely do this
is not guaranteed by the Standard.

I left all this in for emphasis, as it were. :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top