[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-gcc-list] calling function pointers via pointers ?

From: David Brown
Subject: Re: [avr-gcc-list] calling function pointers via pointers ?
Date: Thu, 29 Sep 2005 09:25:13 +0200

> Thank you so much chaps, after an hour experimenting, armed with all
> your suggestion, I have now improved my understanding of pointers
> again... and it now works...
> However, something still causes me trouble apparently....
> The actual/complete declaration of my "menu" data type / structure is :
> struct menu {
> uint8_t options; //options to control the operation of the menu
> uint8_t nb; //number of options present in this menu
> char desc[][21]; //table to store the strings for each menu entry
> void (*fp[])(void); //table to store the pointers to the functions
> };
> The compiler complains that :
> ui.h:29: error: flexible array member not at end of struct
> make: *** [main.o] Error 1
> I got around this by giving a fixed size to 'desc', which worked fine
> for debugging the pointer part of things, but it's otherwise no good of
> course.
> What's the trick ?

Well, at the risk of stating the obvious - the compiler has told you exactly
what the error is.  A flexible array member (i.e., one whose size is not
known from the definition here) can only occur at the end of a struct.
Think about things from the compiler's viewpoint.  If you ask it to access
"menu.nb", it can do knows how far ".nb" is from the start of the "menu".
If you ask it to access "menu.desc[15]", it can figure that out too.  But if
you ask it to access "menu.fp[4]", it doesn't know where to look, as it does
not know how long the entire "desc" array is.  Therefore, the compiler gives
you an error.

Assuming that your "desc" and "fp" arrays are to be the same lengths, then
the solution is to put them together in a structure and have a single
unconstrained array of such pairs.

The other important thing to do is use typedefs.  Use a typedef for every
struct, every pointer type, and every complex type.  They cost nothing on
the target, and hugely improve the readability and maintainability of your
code.  Look at Thomas Buchta's post for an example (except avoid shouting in
all capitals - it makes the code a pain to read).  Or look at these
definitions partly from a menuing system I wrote once (for an msp430, which
can access flash data directly with normal pointers, which makes things
somewhat simpler):

typedef void (*FVoid)(void);
typedef void (*FKeyFunc)(TKeys);

typedef struct {
        FVoid fStart, fUpdate;
        FKeyFunc fKey;
} TScreenData;

struct TMenu;
typedef struct TMenu const *PMenu;

typedef struct {
        const char* name;
        TScreenData screenData;
        PMenu pSubMenu;
} TMenuItem;

typedef struct TMenu {
        const char* title;
        word entries;
        TMenuItem items[];
} TMenu;

It's a little easier to follow than all this "void (*fp[])(void)" crap,
wouldn't you say?



reply via email to

[Prev in Thread] Current Thread [Next in Thread]