Peter
Peter

Reputation: 193

How can I initialise an array of strings that is a member of a struct?

How can I "send" an array of strings to a struct? My question is more, how do I "spell it" in code. I receive the error, that there are braces missing.

I declared a struct with an array of strings (tstrs).

typedef struct
{
    bool dummy;
    char *tdata1;
    char *tdata2;
    char tstrs[30][50];
} SampleSettings;

When I pass data to this struct from main.c it works when I use this code

static char strs[30][50];

SampleSettings sample_settings  = {
    false,"nothing","empty",{"foo","morefoo"}
};

But, if I use e.g. this code

static char strs[30][50];

SampleSettings sample_settings  = {
    false,"nothing","empty",strs
};

the compiler stops with

error: missing braces around initializer [-Werror=missing-braces]

I am aware that this could be a rookie question. Sorry for that.

Upvotes: 2

Views: 625

Answers (5)

Jimbo
Jimbo

Reputation: 4515

this is to do with how one can initialise structures...

Items in initialiser lists must be constant expressions. The string literals "foo" and "more foo" are such constant expressions. strs is not a constant expression so its contents cannot be known at compile time. Therefore the compiler can't use it in an initialiser list.

From C99

All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals. ...

An array of character type may be initialized by a character string literal, optionally enclosed in braces. Successive characters of the character string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.

So for example, you can do

char stringy[10] =  "a string";

which is equivalent to

char stringy[10] = { 'a', ' ', 's', 't', 'r', 'i', 'n', 'g', '\0' };

You cannot do

char stringy1[10] = "string 1";
char stringy2[10] = stringy1;

The reason for this is that stringy1 resolves to the address of the first byte of the array. So here you are trying to initialise an array with an address, (a char * pointer). C cannot do this... this would involve a memcpy of the contents of stringy2 into stringy1 which the compiler will not do... you have to :)

More crom c99...

...the initializer for an object that has aggregate or union type shall be a brace enclosed list of initializers for the elements or named members...

Edit thus for char[] the initialiser list must be a brace enclosed list of chars. The string literal initialiser are just nice syntactic sugar.

Upvotes: 0

user1300630
user1300630

Reputation:

If this is an option too, You can use

memcpy(sample_settings.tstrs, strs, 1500);

outside the initialization block.

Upvotes: 0

Sarwar Erfan
Sarwar Erfan

Reputation: 18068

Option 1

typedef struct
{
    bool dummy;
    char *tdata1;
    char *tdata2;
    char tstrs[30][50];
} SampleSettings;

int main()
{
    SampleSettings sample_settings  = {
        false,"nothing","empty",{"foo","morefoo"}
    };

    return 0;
}

Option 2

Check that I have changed the struct

typedef struct
{
    bool dummy;
    char *tdata1;
    char *tdata2;
    char **tstrs;
} SampleSettings;

int main()
{
    char strs[30][50] = {{0}};
    SampleSettings sample_settings  = {
        false,"nothing","empty",(char **)strs
    };
    return 0;
}

Upvotes: 2

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385174

This is a language limitation.

[C99: 6.7.8/13]: The initializer for a structure or union object that has automatic storage duration shall be either an initializer list as described below, or a single expression that has compatible structure or union type. In the latter case, the initial value of the object, including unnamed members, is that of the expression.

[C99: 6.7.8/14]: An array of character type may be initialized by a character string literal, optionally enclosed in braces. Successive characters of the character string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array.

[C99: 6.7.8/15]: An array with element type compatible with wchar_t may be initialized by a wide string literal, optionally enclosed in braces. Successive wide characters of the wide string literal (including the terminating null wide character if there is room or if the array is of unknown size) initialize the elements of the array.

[C99: 6.7.8/16]: Otherwise, the initializer for an object that has aggregate or union type shall be a brace-enclosed list of initializers for the elements or named members.

There is simply no rule to allow initialisation of an aggregate from the name of another aggregate.

Upvotes: 2

Adrian Panasiuk
Adrian Panasiuk

Reputation: 7343

static char strs[30][50];

SampleSettings sample_settings  = {
    false,"nothing","empty",strs
};

This will try to initialize the first element of the 2d array strs[0][0] to strs.

strs[0][0] = (char) strs;

as can be witnessed with (gcc 4.7.2, -Wall)

a.c:15:1: warning: initialization makes integer from pointer without a cast [enabled by default]
a.c:15:1: warning: (near initialization for ‘sample_settings.tstrs[0][0]’) [enabled by default]

But won't work anyway

a.c:19:1: error: initializer element is not constant
a.c:19:1: error: (near initialization for ‘sample_settings.tstrs[0][0]’)

You could macro define the values

#define STRS  { "foo", "morefoo" }
SampleSettings sample_settings  = {
    false,"nothing","empty", STRS
};

Upvotes: 1

Related Questions