There are several variants possible, here two of them:
struct s
{
char params1[32][64]; // 32 strings each with maximum length of 64 characters
///////////////////////////////////////////////////
char buffer[1024]; // byte buffer for individual strings
char* params2[32]; // 32 pointers you can let point
// to arbitrary positions into buffer
};
If you don't always use all parameters you might want to add size_t numparams; to any of both of above solutions.
When copying, first variant is just fine, with second variant you will have to re-adjust the pointers:
dest.params2[n] = dest.buffer + (source.params2[n] - source.buffer);
With second variant, don't forget to leave space for terminating null pointers. A struct with data might then look like this:
buffer == "hello world\0hola mundo\0salut monde\0\0\0 ...";
// first parameter c a n be implicit: buffer
params2[0] == buffer + 12;
params2[1] == buffer + 23;
numParams == 3; // including the implicit parameter
Alternatively first parameter might always point to buffer's begin, then you can access all parameters consistently without any special handling like p = n == 0 ? buffer : params[n-1].
Initialisation can look like this:
struct s g_s =
{
.params1 =
{
"hello world",
"hola mundo",
"salut monde",
},
.buffer = "hello world\0hola mundo\0salut monde",
.params2 =
{
g_s.buffer + 12,
g_s.buffer + 23,
},
.numParams = 3,
};
Unfortunately you need to count the offsets for second variant on your own (you might write a helper script doing that for you...).
[]instead of[15]