user2030243
user2030243

Reputation: 47

array of strings within a struct in C without allocating

I want to initialize a structure with an array of string without doing dynamic allocation. Is it possible? I had thought of something like this but it doesn't work:

struct st_request {
int GRID;
char NAME[15];
char (*PARAM)[15];
};
typedef struct st_request request;

request myrequest = {
 .GRID=1,
 .NAME="GLOB",
 .PARAM={"RR1","RR3"}
}

An idea? Thanks for your solutions.

Upvotes: 0

Views: 163

Answers (3)

Aconcagua
Aconcagua

Reputation: 25516

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...).

Upvotes: 2

Andreas Wenzel
Andreas Wenzel

Reputation: 24726

The line

char (*PARAM)[15];

declares a single pointer PARAM which points to an array of type char[15], i.e. to an array of 15 elements, in which each element has the type char.

You probably want to write

char *PARAM[15];

which declares an array of 15 pointers, in which each pointer has the type char*. In contrast to the pointer mentioned earlier, which points to an entire array, these 15 pointers only point to a single character.

In C, when handling strings, it is normal to use pointers to the first character of a null-terminated character sequence. Pointers to entire arrays are normally only used in the context of multi-dimensional arrays, because the size information of the referenced object is needed to calculate the offset in a multi-dimensional array.

Note that it is not normal to write the names of variables in upper-case. This is normally reserved for constants.

Also, there is a ; missing in the last line of your code.

Upvotes: 1

Tarik
Tarik

Reputation: 11209

You could try the following:

#define PARAM_SIZE 20;

struct st_request {
int GRID;
char NAME[15];
char PARAM[15*PARAM_SIZE];
};

request myrequest = {
 .GRID=1,
 .NAME="GLOB"
}

strcpy (&myrequest.PARAM[0*PARAM_SIZE], "RR1");
strcpy (&myrequest.PARAM[1*PARAM_SIZE], "RR3");

Upvotes: 0

Related Questions