Reputation: 193
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
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 char
s. The string literal initialiser are just nice syntactic sugar.
Upvotes: 0
Reputation:
If this is an option too, You can use
memcpy(sample_settings.tstrs, strs, 1500);
outside the initialization block.
Upvotes: 0
Reputation: 18068
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;
}
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
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
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