Reputation: 51
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?
Upvotes: 5
Views: 455
Reputation: 44250
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
};
Upvotes: 2
Reputation: 755054
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.
Upvotes: 0
Reputation: 320777
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.
Upvotes: 3
Reputation: 141658
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
Upvotes: 4
Reputation: 1577
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
Upvotes: 4