cpointersc-preprocessorstatic-array

C Preproccessor Pointer Swizzling


I'm trying to avoid a problem in a static table whereby one table references another which references the original table. The compiler complains about the definition of one of the table members not being found. To work around the problem, I've been mocking up some test code, would something along these lines work? Is something like what I'm attempting to do even possible?

Below is the code for reference:

#define SWIZTBLMAX 256

#define TERM( NAME , ...) \
    static cli_term NAME { __VA_ARGS__ }; swizzle_tbl[__COUNTER__] = { &NAME, "NAME" };

typedef struct cli_term
{
    char* name;
    cli_term* parent;
    cli_term* child;
}cli_termt;

typedef struct swiz_ent
{
    cli_term* t;
    char* n;
}swiz_ent;

static swiz_ent swizzle_tbl[SWIZTBLMAX];

static cli_term* swizzle(const char* n)
{
    int i;
    for(i=0;i<SWIZTBLMAX;i++)
    {
        if(strcmp(n,swizzle_tbl[i].n)==0)
            return swizzle_tbl[i].t;
    }
return NULL;
}

TERM( ct_show_test, "test",  swizzle("ct_show"), NULL )
TERM( ct_quit, "quit", NULL, NULL )
TERM( ct_show, "show", NULL, swizzle("ct_show_test") )

So, my idea was to defer the pointer assignment to runtime, I've done something similar when writing objects to disk and back. Is there any way I can create a static table like this? (With pointers to other structs statically assigned)


Solution

  • Your TERM macro cannot be used outside the scope of a function because it tries to write assignments instead of declarations:

    #define TERM( NAME , ...) \
        static cli_term NAME { __VA_ARGS__ }; \
        swizzle_tbl[__COUNTER__] = { &NAME, "NAME" };
    

    The swizzle_tbl[__COUNTER__] is an assignment; you can't do assignments outside of a function. It also must be upgraded to assign a compound literal:

    #define TERM( NAME , ...) \
        static cli_term NAME { __VA_ARGS__ }; \
        swizzle_tbl[__COUNTER__] = (swiz_ent){ &NAME, "NAME" };
    

    Using TERM inside a function may or may not help; the static cli_term variables won't be accessible outside the function except via the swizzle_tbl. This may be a good thing. If everything else is OK with that (nothing else needs to access the data by name), this should be OK.

    You'd need to think about what __COUNTER__ does. It is not a part of standard C, and therefore isn't portable. You could use a local variable in the function in place of __COUNTER__.