Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

initializng a C array with repetitive data

I would like to initialize an array of structs, with the same element repetitively, ie

struct st ar[] = { {1,2}, {1,2}, {1,2} };

However I do NOT want to run any code for that, I wish that the layout of the memory upon program's execution would be like so, without any CPU instructions involved (it would increase boot time on very slow CPU and relatively large arrays).

This makes sense, when using the array as mini ad-hoc database (maps id to struct) and when one wishes to use a default value to all database values.

My best solution was to use something of the form

#define I {1,2}
struct st ar[SIZE_OF_ARRAY] = { I,I,I };

So that the compiler will warn me if I'm having too much or too little Is. But this is far from ideal.

I think there's no solution for that in ANSI-C, but I thought that maybe there's a macro-abuse, or gcc extension that would do the work. Ideally I would like a standard solution, but even compiler specific ones would suffice.

I thought That I would somehow be able to define a macro recursively so that I(27) would be resolved to 27 {1,2}s, but I don't think that's possible. But maybe I'm mistaken, is there any hack for that?

Maybe inline assemby would do the trick? It would be very easy to define such memory layout with MASM or TASM, but I'm not sure it is possible to embed memory layout instructions within C code.

Is there any linker trick that would lure it to initialize memory according to my orders?

PS I know I can generate automatically C file with some script. Using custom scripts is not desirable. If I'd use a custom script, I'll invent a C-macro REP(count,exp,sep) and would write a mini-C-preprocessor to replace that with exp sep exp sep ... exp {exp appears count time}.

like image 357
Elazar Leibovich Avatar asked May 10 '09 08:05

Elazar Leibovich


3 Answers

The boost preprocessor library (which works fine for C) could help.

#include <boost/preprocessor/repetition/enum.hpp>

#define VALUE(z, n, text) {1,2}

struct st ar[] = {
    BOOST_PP_ENUM(27, VALUE, _)
};

#undef VALUE

If you wish to use it, you'll just need the boost/preprocessor directory from boost - it's entirely self contained.

Although, it does have some arbitrary limits on the number of elements (I think it's 256 repetitions in this case). There is an alternative called chaos which doesn't, but it's experimental and will only work for preprocessors that follow the standard precisely (GCC's does).

like image 120
Daniel James Avatar answered Oct 24 '22 00:10

Daniel James


The easiest way I can think of is to write a script to generate the initialisers that you can include into your C code:

{1,2},
{1,2},
{1,2}

Then in your source:

struct st ar[] = {
    #include "init.inc"
};

You can arrange your Makefile to generate this automatically if you like.

like image 37
Greg Hewgill Avatar answered Oct 23 '22 23:10

Greg Hewgill


I'm guessing you can, on the file with the array definition, do:

#include "rep_array_autogen.c"
struct st ar[SIZE_OF_ARRAY] = REPARRAY_DATA;

and have your Makefile generate rep_array_autogen.c with a format like

#define SIZE_OF_ARRAY 3
#define REPARRAY_DATA {{1, 2}, {1, 2}, {1, 2}, }

Since rep_array_autogen.c is built on your machine, it would be just as fast as hand-coding it in there.

like image 27
Tordek Avatar answered Oct 23 '22 23:10

Tordek