Why can't I initialize an array of cstrings like this?
Question
char sXSongBuffer[20][30];
sXSongBuffer = {"Thriller", "Don't Stop Till You Get Enough", "Billy Jean"};
Why does this return the error expected expression before ‘{’ token
? The reason I want to initialize my array like this is so that I can change its contents like this later:
sXSongBuffer = {"New Song", "More Music From Me"};
Solution
You can't assign to arrays in C. C allows initializing arrays with values that are compile-time constants. If you want to change the values later, or set values that are not compile-time constants, you must assign to a particular index of the array manually.
So, your assignment to sXSongBuffer
is disallowed in C. Moreover, since sXSongBuffer[0]
to sXSongBuffer[19]
are arrays too, you can't even say: sXSongBuffer[0] = "New Song";
Depending upon what you want, this may work for you:
/* declare sXSongBuffer as an array of pointers */
char *sXSongBuffer[30] = {
"Thriller",
"Don't Stop Till You Get Enough",
"Billy Jean",
NULL /* set the rest of the elements to NULL */
};
size_t i;
/* and then later in your code */
sXSongBuffer[0] = "New Song";
sXSongBuffer[1] = "More Music From Me";
for (i=2; i < sizeof sXSongBuffer; ++i)
sXSongBuffer[i] = NULL;
But the above only works if you know all your strings at compile time. If not, you will have to decide if you want "big-enough" arrays, or if you need dynamic memory for the strings and/or the number of strings. In both cases, you will want to use an equivalent of strcpy()
to copy your strings.
Edit: To respond to the comment:
You're declaring an array of 30 char pointers with the first three elements pointing to buffers the size of the strings, ie the buff pointed to by
sXSongBuffer[0]
won't hold any string larger than"Thriller"
and if he doessXSongBuffer[0] = malloc(32);
He'll get a minor memory leek. Also, he'll have tomalloc
memory for each of the rest of the slots in the array. He should either use 2d char arrays like in the OP + a designated init, ormalloc
each buffer at run time and copy in the values. He'll also need to remember tofree
any memory hemalloc
s.
sXSongBuffer
in char *sXSongBuffer[30];
is an array of size 30, with each element being a char *
, a pointer to char
. When I do:
char *sXSongBuffer[30];
each of those 30 pointers is uninitialized. When I do:
char *sXSongBuffer[30] = { "Thriller", ... };
I set the pointers to different read-only locations. There is nothing preventing me to then "re-point" the pointers somewhere else. It is as if I had:
char *data = "Hello";
printf("%s\n", data);
data = "Hello, world";
printf("%s\n", data);
In the above snippet, I assign data
to "Hello"
first, and then change it to point to a longer string later. The code I had above in my answer did nothing more than reassign sXSongBuffer[i]
to something else later, and since sXSongBuffer[i]
is a pointer, the assignment is OK. In particular, sXSongBuffer[0]
is a char *
, and can point to any valid location that has a char
in it.
As I said later in my answer, if the strings aren't known at compile-time, this scheme doesn't work, and one has to either use arrays with "big enough" sizes, or dynamically allocate memory that's big enough.
OTHER TIPS
C does not have general-purpose array literals. The {}
list syntax only works when initializing, i.e. when assigning the value in the same statement that declares the variable.
You cannot just write
char sXSongBuffer[20][30];
sXSongBuffer = {"Thriller", "Don't Stop Till You Get Enough", "Billy Jean"};
You must either initialize array at once (but it will containt only 3 items):
char * sXSongBuffer[]= {"Thriller", "Don't Stop Till You Get Enough", "Billy Jean"};
Or either use stnrcpy
on every item:
char sXSongBuffer[20][30];
strncpy(sXSongBuffer[0],"Thriller",29);
strncpy(sXSongBuffer[1],"Don't Stop Till You Get Enough",29);
strncpy(sXSongBuffer[2],"Billy Jean",29);
Take a look at Designated Initializers.
#include <stdio.h>
int main (void) {
char a[6][6] = { [2] = "foo", [4] = "bar" };
for (int i=0; i<6; ++i)
printf("%d == %s\n", i, a[i]);
return 0;
}
This is a c99 feature. Compile with:
gcc -W -std=c99 2dInit.c -o 2dInit
This outputs:
0 ==
1 ==
2 == foo
3 ==
4 == bar
5 ==
In your case you want to do:
char sXSongBuffer[20][30] = {
[0] = "Thriller",
[1] = "Don't Stop Till You Get Enough",
[2] = "Billy Jean"
};