defines and structure instantiation

Discussion in 'C Programming' started by Rich, May 27, 2006.

  1. Rich

    Rich Guest

    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!
     
    Rich, May 27, 2006
    #1
    1. Advertising

  2. Rich wrote:
    > 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
     
    Robert Gamble, May 27, 2006
    #2
    1. Advertising

  3. Rich

    Rich Guest

    Robert Gamble wrote:
    >
    > #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.
     
    Rich, May 27, 2006
    #3
  4. Rich wrote:
    > Robert Gamble wrote:
    > >
    > > #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
     
    Robert Gamble, May 27, 2006
    #4
  5. Robert Gamble wrote:
    > Rich wrote:
    > > Robert Gamble wrote:
    > > >
    > > > #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
     
    Robert Gamble, May 27, 2006
    #5
  6. Rich

    Chris Torek Guest

    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 wrote:
    >>>
    >>>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.

    >Robert Gamble wrote:
    >> 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


    This is one of the big problems ...

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


    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.)

    >> I would do the initialization seperately if I were you.


    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.

    In article <>,
    Robert Gamble <> wrote:
    >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. :)
    --
    In-Real-Life: Chris Torek, Wind River Systems
    Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
    email: forget about it http://web.torek.net/torek/index.html
    Reading email is like searching for food in the garbage, thanks to spammers.
     
    Chris Torek, Jun 3, 2006
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. exquisitus
    Replies:
    12
    Views:
    22,698
    Tilman Bohn
    Feb 19, 2005
  2. Replies:
    2
    Views:
    483
    marbac
    May 8, 2005
  3. theotyflos
    Replies:
    3
    Views:
    495
    Thomas Matthews
    Feb 19, 2004
  4. Patrick Kowalzick
    Replies:
    2
    Views:
    288
    Patrick Kowalzick
    Mar 10, 2006
  5. Replies:
    1
    Views:
    598
    Salt_Peter
    Dec 25, 2006
Loading...

Share This Page