1

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)

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Brian
  • 145
  • 1
  • 3
  • 13
  • You seem to suffer from the [XY-problem](http://xyproblem.info/). It might help if you could make another question with the problem that lead you to this approach. I'm not sure what to make out of your code because I'm not sure what problem you want to solve. – fuz Mar 20 '15 at 23:18
  • Oops, I want to make it so I can statically define the terms while avoiding that cyclic reference. The code above is supposed to defer the assignment of the pointers (and avoid the cyclic reference) by using the preprocessor to fill in a name -> pointer table which is referenced at runtime to fill in the pointers. – Brian Mar 20 '15 at 23:27
  • The XY-problem isn't the problem you have with your code, what it is is explained in the article I linked. You might want to read it, it's not very long. – fuz Mar 20 '15 at 23:29
  • Does the answer I provide help with your original problem? – fuz Mar 20 '15 at 23:32

2 Answers2

2

You can have cyclical references in global variables by declaring the variables before you define them:

struct foo {
    struct foo *fooptr;
};

extern struct foo variable1;
extern struct foo variable2;

struct foo variable1 = { &variable2 };
struct foo variable2 = { &variable1 };
fuz
  • 88,405
  • 25
  • 200
  • 352
1

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

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278