5

I have structure like below

typedef struct
{
    int a;
    int b;
    int c;
} my_struct;

and in another file I have declared a variable of this my_struct type, like below.

my_struct strct_arr[MAX];

Where MAX is a macro which is a configurable value that is a multiple of 18 (18 or 36 or 54 and so on.. it may go up to 18*n times).

I have to initialize the structure with {0xff,0,0}. So, how to initialize whole array of structure my_struct strct_arr[MAX]; with my initial values without using any kind of loops.

I am expecting the output as below:

my_struct strct_arr[MAX]={
    {0xff,0,0},
    {0xff,0,0},
    {0xff,0,0},
    {0xff,0,0},
    …
};

But without knowing MAX value, how to initialize it?

jruizaranguren
  • 12,679
  • 7
  • 55
  • 73
PSR
  • 51
  • 5

5 Answers5

4

There is GCC extension for this. Try this

#define MAX 18
my_struct strct_arr[MAX]={ [0 ... (MAX - 1)] = {0xff,0,0}};

Check https://gcc.gnu.org/onlinedocs/gcc-4.2.1/gcc/Designated-Inits.html

Sanket Parmar
  • 1,477
  • 12
  • 9
4

Yes, this is possible using the C preprocessor!

#include <stdio.h>
#include <boost/preprocessor/repetition/repeat.hpp>

#define INITS(z, n, t) { 0xFF, 0, 0 },
#define REP(item, n) BOOST_PP_REPEAT(n, INITS, item)

#define MAX 123

typedef struct { int a,b,c; } my_struct;

my_struct ms[] = { REP(, MAX) };

int main()
{
    // Check it worked
    printf("%d\n", (int)(sizeof ms / sizeof *ms));
}

Note: boost is a package of C++ stuff, however the boost/preprocessor just uses the preprocessor features which are common to both languages. If your implementation doesn't allow this #include by default, you can find a copy of repeat.hpp from the boost source code.

Also, BOOST_PP_REPEAT defaults to a max of 256. If your MAX is bigger than this, you can edit repeat.hpp to allow bigger values, it should be obvious what to do from there.

Note: this post describes a system for recursive macro that would not require the same sort of implementation as repeat.hpp uses, but I haven't been able to get it to work.

Credit: this post

Community
  • 1
  • 1
M.M
  • 138,810
  • 21
  • 208
  • 365
  • I knew there had to be a preprocessor solution. The issue started with `#define MAX *something*`; a problem born in the preprocessor. The solution had to come from there too. ;) And as I suspected, it's loathsome (yet I can't look away)! +1 for not letting me down. :) – DavidO Jun 18 '14 at 05:11
3

Well, there's is no direct and immediate syntax in standard C to specify an initializer that would do what you want. If you wanted to initialize the whole thing with zeros, then = { 0 } would work regardless of size, but that 0xff makes it a completely different story. GCC compiler supports a non-standard extension that works in such cases (see Sanket Parmar's answers for details), but alas it is not standard.

There's also a non-standard memcpy hack that is sometimes used to fill memory regions with repetitive patterns. In your case it would look as follows

my_struct strct_arr[MAX] = { { 0xff, 0, 0 } };
memcpy(strct_arr + 1, strct_arr, sizeof strct_arr - sizeof *strct_arr);

But this is a hack, since it relies on memcpy doing its copying in byte-by-byte fashion and in strictly left-to-right direction (i.e. from smaller memory addresses to larger ones). However, that's not guaranteed by the language specification. If you want to "legalize" this trick, you have to write your own version of my_memcpy that works in that way specifically (byte-by-byte, left-to-right) and use it instead. Of course, this is formally a cyclic solution that is not based entirely on initializer syntax.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • Even if this memcpy "works" it would be because the implementation of memcpy has a loop in it, so you lose nothing performance-wise by explicitly putting the loop in your own code. – M.M Jun 18 '14 at 05:23
2

Paraphrasing Jonathan Leffler's solution:

struct my_struct { char c, int a; int b; }

#define MAX 135

#define INIT_X_1     { 0xff, 0, 0 }
#define INIT_X_2     INIT_X_1, INIT_X_1
#define INIT_X_4     INIT_X_2, INIT_X_2
#define INIT_X_8     INIT_X_4, INIT_X_4
#define INIT_X_16    INIT_X_8, INIT_X_8
#define INIT_X_32    INIT_X_16, INIT_X_16
#define INIT_X_64    INIT_X_32, INIT_X_32
#define INIT_X_128   INIT_X_64, INIT_X_64

struct my_struct strct_arr[MAX] =
{
#if (MAX & 1)
    INIT_X_1,
#endif
#if (MAX & 2)
    INIT_X_2,
#endif
#if (MAX & 4)
    INIT_X_4,
#endif
#if (MAX & 8)
    INIT_X_8,
#endif
#if (MAX & 16)
    INIT_X_16,
#endif
#if (MAX & 32)
    INIT_X_32,
#endif
#if (MAX & 64)
    INIT_X_64,
#endif
#if (MAX & 128)
    INIT_X_128,
#endif
};
Community
  • 1
  • 1
wildplasser
  • 43,142
  • 8
  • 66
  • 109
  • Mr Wildplasser, This is the way I have tried it my self after some struggle. But the thing is, I cannot restrict my initialization up to 54 or 62 or even 128. It's really hard to get an idea on MAX number value which will be varied by the user configuration. So, I have created a perl script which will generate one macro based on the configured MAX value. In this way, I don't make C code burden in run time. – PSR Jun 26 '14 at 11:26
  • Well, it is not that hard to extend this solution to 512, 1024, ... and beyond. Everery doubling will only cost you a few (four) extra lines. But codegeneration is always an option. – wildplasser Jun 28 '14 at 16:11
0

Just for sake of variety, since you know the array will be a multiple of 18, you could use something like this:

#define INIT_X_1     { 0xff, 0, 0 }
#define INIT_X_3     INIT_X_1, INIT_X_1, INIT_X_1
#define INIT_X_9     INIT_X_3, INIT_X_3, INIT_X_3
#define INIT_X_18    INIT_X_9, INIT_X_9

my_struct strct_arr[MAX] =
{
    INIT_X_18,
#if MAX > 18
    INIT_X_18,
#if MAX > 36
    INIT_X_18,
#endif
#endif
};

This will work without needing C99 support (it would even work with pre-standard C), GCC extensions, or Boost Preprocessor library. In every other respect, the other solutions are better.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • I see that you have considered it up to 54 times. I am afraid that if my array size is 64, will it initialize 64 times with structure values. Can you give any possibilities if I need to continue up to the max value, which is a configurable value? – PSR Jun 26 '14 at 09:25
  • Use [wildplasser](http://stackoverflow.com/users/905902/wildplasser)'s [generalization](http://stackoverflow.com/a/24288670/15168) of my solution, as long as you have an upper bound to work with. Otherwise, you'll need to use an extra-linguistic mechanism such as you mention in your comments below his answer. I tailored my answer to the multiples of 18 you mentioned in your question. Failing that, consider using a single initializer and copying that to your array at runtime. It won't take long compared to everything else that you're going to do. – Jonathan Leffler Jun 26 '14 at 14:01