static (non-zero) initialization of an array of structs (array of length #define LEN)

A

anon.asdf

Here is a possible solution in the form of working code: [snip]
#include <stdio.h>

#define CONCAT_X(mp_t1, mp_t2)mp_t1##mp_t2
#define CONCAT(mp_t1, mp_t2)CONCAT_X(mp_t1, mp_t2)

#define PLACE_X(mp_fp)mp_fp()
#define PLACE_1(mp_fp)PLACE_X(mp_fp)
#define PLACE_2(mp_fp)PLACE_X(mp_fp), PLACE_X(mp_fp)
#define PLACE_3(mp_fp)PLACE_2(mp_fp), PLACE_X(mp_fp)
#define PLACE_4(mp_fp)PLACE_3(mp_fp), PLACE_X(mp_fp)
#define PLACE_5(mp_fp)PLACE_4(mp_fp), PLACE_X(mp_fp)
#define PLACE_6(mp_fp)PLACE_5(mp_fp), PLACE_X(mp_fp)
#define PLACE_7(mp_fp)PLACE_6(mp_fp), PLACE_X(mp_fp)
#define PLACE_8(mp_fp)PLACE_7(mp_fp), PLACE_X(mp_fp)
#define PLACE_9(mp_fp)PLACE_8(mp_fp), PLACE_X(mp_fp)
#define PLACE_10(mp_fp)PLACE_9(mp_fp), PLACE_X(mp_fp)
#define PLACE(mp_fp, mp_d)CONCAT(PLACE_, mp_d)(mp_fp)

It also works with CONCAT_X (directly) on the line above:
#define PLACE(mp_fp, mp_d)CONCAT_X(PLACE_, mp_d)(mp_fp)
typedef struct foo_s {
int i;
char a;

} foo_t;

#define FOO_STATICINIT(mp_fp, mp_d) { \
PLACE(mp_fp, mp_d) \

}

^In case someone just copies and gets a compile error - the reason
will be the empty line above }.
#define MYARRAY_DEPTH_1() 4
#define MYARRAY_DEPTH_2() 7
#define MYARRAY_INIT_1() {1, 'x'}
#define MYARRAY_INIT_2() {5, 'a'}

static foo_t g_foo1[MYARRAY_DEPTH_1()] =
FOO_STATICINIT(MYARRAY_INIT_1, MYARRAY_DEPTH_1());

static foo_t g_foo2[MYARRAY_DEPTH_2()] =
FOO_STATICINIT(MYARRAY_INIT_2, MYARRAY_DEPTH_2());

int main(void) {
{
int i;

for(i = 0; i < MYARRAY_DEPTH_1(); ++i) {
printf("g_foo1[%i].i(%i)\ng_foo1[%i].a(%c)\n----\n",
i, g_foo1.i, i, g_foo1.a);
}

puts("\n\n_____________________________\n\n");

for(i = 0; i < MYARRAY_DEPTH_2(); ++i) {
printf("g_foo2[%i].i(%i)\ng_foo2[%i].a(%c)\n----\n",
i, g_foo2.i, i, g_foo2.a);
}

}

puts("\n\n\n\
_______________________\npress <enter> to exit...\n");
return getchar();

} [snip]
Does that do what you want?


Yes, unbelievable!
Thanks for that! I'm trying to figure out how it does what it does!

Things like removing "()" from a macro, and passing it along
#define MYARRAY_INIT_1() {1, 'x'}
...
static foo_t g_foo1[MYARRAY_DEPTH_1()] =
FOO_STATICINIT(MYARRAY_INIT_1, MYARRAY_DEPTH_1());

and then putting it back at the end, are sneaky! :)
#define PLACE_X(mp_fp)mp_fp()

And I've got an idea what it's for, but I cannot deduce the
"semantics"...
I'll probably have to read up on the preprocessor to fully understand
it.

-Albert
 
A

anon.asdf

#include <stdio.h>

#define CONCAT_X(mp_t1, mp_t2)mp_t1##mp_t2
#define CONCAT(mp_t1, mp_t2)CONCAT_X(mp_t1, mp_t2)

#define PLACE_X(mp_fp)mp_fp()
#define PLACE_1(mp_fp)PLACE_X(mp_fp)
#define PLACE_2(mp_fp)PLACE_X(mp_fp), PLACE_X(mp_fp)
#define PLACE_3(mp_fp)PLACE_2(mp_fp), PLACE_X(mp_fp)
#define PLACE_4(mp_fp)PLACE_3(mp_fp), PLACE_X(mp_fp)
#define PLACE_5(mp_fp)PLACE_4(mp_fp), PLACE_X(mp_fp)
#define PLACE_6(mp_fp)PLACE_5(mp_fp), PLACE_X(mp_fp)
#define PLACE_7(mp_fp)PLACE_6(mp_fp), PLACE_X(mp_fp)
#define PLACE_8(mp_fp)PLACE_7(mp_fp), PLACE_X(mp_fp)
#define PLACE_9(mp_fp)PLACE_8(mp_fp), PLACE_X(mp_fp)
#define PLACE_10(mp_fp)PLACE_9(mp_fp), PLACE_X(mp_fp)
#define PLACE(mp_fp, mp_d)CONCAT(PLACE_, mp_d)(mp_fp)

It also works with CONCAT_X above, i.e.
#define PLACE(mp_fp, mp_d)CONCAT_X(PLACE_, mp_d)(mp_fp)

typedef struct foo_s {
int i;
char a;

} foo_t;

#define FOO_STATICINIT(mp_fp, mp_d) { \
PLACE(mp_fp, mp_d) \

}

In case someone is just copy-pasting: to prevent a compile-error, the
empty line above "}" should be removed
#define MYARRAY_DEPTH_1() 4
#define MYARRAY_DEPTH_2() 7
#define MYARRAY_INIT_1() {1, 'x'}
#define MYARRAY_INIT_2() {5, 'a'}

static foo_t g_foo1[MYARRAY_DEPTH_1()] =
FOO_STATICINIT(MYARRAY_INIT_1, MYARRAY_DEPTH_1());

static foo_t g_foo2[MYARRAY_DEPTH_2()] =
FOO_STATICINIT(MYARRAY_INIT_2, MYARRAY_DEPTH_2());

int main(void) {
{
int i;

for(i = 0; i < MYARRAY_DEPTH_1(); ++i) {
printf("g_foo1[%i].i(%i)\ng_foo1[%i].a(%c)\n----\n",
i, g_foo1.i, i, g_foo1.a);
}

puts("\n\n_____________________________\n\n");

for(i = 0; i < MYARRAY_DEPTH_2(); ++i) {
printf("g_foo2[%i].i(%i)\ng_foo2[%i].a(%c)\n----\n",
i, g_foo2.i, i, g_foo2.a);
}

}

puts("\n\n\n\
_______________________\npress <enter> to exit...\n");
return getchar();

}


Yes! Unbelievable!
Thanks for that!

I'm trying to understand it:

..
..

Things like removing ()
#define MYARRAY_INIT_1() {1, 'x'}
...
static foo_t g_foo1[MYARRAY_DEPTH_1()] =
FOO_STATICINIT(MYARRAY_INIT_1, MYARRAY_DEPTH_1());

and then including them at the end are sneaky! :)
#define PLACE_X(mp_fp)mp_fp()
..
..
I believe I know why this is done (prevent premature expansion), but I
think I really need to read some more about the C preprocessor to
understand the exact "semantics".

Thanks -Albert
 
C

Chris Thomasson

Chris Thomasson said:
news:[email protected]... [...]

#define PLACE_X(mp_fp)mp_fp()
#define PLACE_1(mp_fp)PLACE_X(mp_fp)
#define PLACE_2(mp_fp)PLACE_X(mp_fp), PLACE_X(mp_fp)
#define PLACE_3(mp_fp)PLACE_2(mp_fp), PLACE_X(mp_fp)
#define PLACE_4(mp_fp)PLACE_3(mp_fp), PLACE_X(mp_fp)
#define PLACE_5(mp_fp)PLACE_4(mp_fp), PLACE_X(mp_fp)
#define PLACE_6(mp_fp)PLACE_5(mp_fp), PLACE_X(mp_fp)
#define PLACE_7(mp_fp)PLACE_6(mp_fp), PLACE_X(mp_fp)
#define PLACE_8(mp_fp)PLACE_7(mp_fp), PLACE_X(mp_fp)
#define PLACE_9(mp_fp)PLACE_8(mp_fp), PLACE_X(mp_fp)
#define PLACE_10(mp_fp)PLACE_9(mp_fp), PLACE_X(mp_fp)
#define PLACE(mp_fp, mp_d)CONCAT(PLACE_, mp_d)(mp_fp)

[...]

You can conditionally specialize the PLACE_ macro function table for
specific sizes. For instance, lets say you need to work with arrays larger
than [10], perhaps you need 50:

--------------
#if ! defined(PLACE_50)
#define PLACE_50(mp_fp) \
PLACE_10(mp_fp), PLACE_10(mp_fp), PLACE_10(mp_fp), \
PLACE_10(mp_fp), PLACE_10(mp_fp)
#endif
--------------



Now you can do something like:

--------------
typedef struct foo_s {
char a;
char b;
char c;
} foo_t;

#define INIT() {'a', 'b', 'c'}

static foo_t g_foo[50] = {PLACE(INIT, 50)}

[...]
--------------

So, it can be "extended" to some fairly large array sizes...





Also, if you really want to get tricky... You could paramertize the
"delayed" macro call, (e.g., mp_fp parameter) with some state. For instance,
you could pass it an index:
--------------
#define PLACE_X(mp_fp, mp_idx)mp_fp(mp_idx)
#define PLACE_1(mp_fp)PLACE_X(mp_fp, 0)
#define PLACE_2(mp_fp)PLACE_1(mp_fp), PLACE_X(mp_fp, 1)
#define PLACE_3(mp_fp)PLACE_2(mp_fp), PLACE_X(mp_fp, 2)
#define PLACE_4(mp_fp)PLACE_3(mp_fp), PLACE_X(mp_fp, 3)
#define PLACE_5(mp_fp)PLACE_4(mp_fp), PLACE_X(mp_fp, 4)
#define PLACE_6(mp_fp)PLACE_5(mp_fp), PLACE_X(mp_fp, 5)
#define PLACE_7(mp_fp)PLACE_6(mp_fp), PLACE_X(mp_fp, 6)
#define PLACE_8(mp_fp)PLACE_7(mp_fp), PLACE_X(mp_fp, 7)
#define PLACE_9(mp_fp)PLACE_8(mp_fp), PLACE_X(mp_fp, 8)
#define PLACE_10(mp_fp)PLACE_9(mp_fp), PLACE_X(mp_fp, 9)
#define PLACE(mp_fp, mp_d)CONCAT(PLACE_, mp_d)(mp_fp)
--------------



Now you can do something cool like:

--------------

static char const g_data_0[] = "Data0";
static char const g_data_1[] = "Data2";
static char const g_data_2[] = "Data3";

typedef struct foo_s {
size_t id;
char const* const data;
} foo_t;

#define INIT(mp_idx) { (mp_idx), CONCAT(g_data_, mp_idx) }

static foo_t g_foo[8] = {PLACE(INIT, 3)}

[...]
--------------




There is a lot of crazy shi% you can do with the c pre-processor..

:^0




You could paramertize the "delayed" macro call even further! For instance,
you could pass it a token:
--------------
#define PLACE_X(mp_fp, mp_idx, mp_t)mp_fp(mp_idx, mp_t))
#define PLACE_1(mp_fp, mp_t)PLACE_X(mp_fp, 0, mp_t)
#define PLACE_2(mp_fp, mp_t)PLACE_1(mp_fp, mp_t), PLACE_X(mp_fp, 1, mp_t)
#define PLACE_3(mp_fp, mp_t)PLACE_2(mp_fp, mp_t), PLACE_X(mp_fp, 2, mp_t)
#define PLACE_4(mp_fp, mp_t)PLACE_3(mp_fp, mp_t), PLACE_X(mp_fp, 3, mp_t)
#define PLACE_5(mp_fp, mp_t)PLACE_4(mp_fp, mp_t), PLACE_X(mp_fp, 4, mp_t)
#define PLACE_6(mp_fp, mp_t)PLACE_5(mp_fp, mp_t), PLACE_X(mp_fp, 5, mp_t)
#define PLACE_7(mp_fp, mp_t)PLACE_6(mp_fp, mp_t), PLACE_X(mp_fp, 6, mp_t)
#define PLACE_8(mp_fp, mp_t)PLACE_7(mp_fp, mp_t), PLACE_X(mp_fp, 7, mp_t)
#define PLACE_9(mp_fp, mp_t)PLACE_8(mp_fp, mp_t), PLACE_X(mp_fp, 8, mp_t)
#define PLACE_10(mp_fp, mp_t)PLACE_9(mp_fp, mp_t), PLACE_X(mp_fp, 9, mp_t)
#define PLACE(mp_fp, mp_t, mp_d)CONCAT(PLACE_, mp_d)(mp_fp, mp_t)
--------------






Now you can do something cool like:

--------------

static char const g_data_0[] = "Data0";
static char const g_data_1[] = "Data2";
static char const g_data_2[] = "Data3";

typedef struct foo_s {
size_t id;
char const* const data;
} foo_t;

#define INIT(mp_idx, mp_t) { (mp_idx), CONCAT(mp_t, mp_idx) }

static foo_t g_foo[8] = {PLACE(INIT, g_data_, 3)}

[...]
 
C

Chris Thomasson

[...]
Now you can do something cool like:

--------------

static char const g_data_0[] = "Data0";
static char const g_data_1[] = "Data2";
static char const g_data_2[] = "Data3";

typedef struct foo_s {
size_t id;
char const* const data;
} foo_t;

#define INIT(mp_idx) { (mp_idx), CONCAT(g_data_, mp_idx) }

static foo_t g_foo[8] = {PLACE(INIT, 3)}
^^^^^^^^^^^^^^^
that should of course be:

static foo_t g_foo[3] = {PLACE(INIT, 3)};

[...]

Now you can do something cool like:

--------------

static char const g_data_0[] = "Data0";
static char const g_data_1[] = "Data2";
static char const g_data_2[] = "Data3";

typedef struct foo_s {
size_t id;
char const* const data;
} foo_t;

#define INIT(mp_idx, mp_t) { (mp_idx), CONCAT(mp_t, mp_idx) }

static foo_t g_foo[8] = {PLACE(INIT, g_data_, 3)}
^^^^^^^^^^^^^^^^^^^

ditto:

static foo_t g_foo[3] = {PLACE(INIT, 3)};



Sorry about that.
 

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

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,038
Latest member
OrderProperKetocapsules

Latest Threads

Top