将字符串分配给字符数组

接下来的事情让我有点惊讶。

例子一:

char s[100] = "abcd"; // declare and initialize - WORKS

例二:

char s[100]; // declare
s = "hello"; // initalize - DOESN'T WORK ('lvalue required' error)

我想知道为什么第二种方法行不通。它似乎是自然的(它与其他数据类型一起工作) ?有人能给我解释一下这背后的逻辑吗?

306295 次浏览

Initialization and assignment are two distinct operations that happen to use the same operator ("=") here.

There is no such thing as a "string" in C. In C, strings are one-dimensional array of char, terminated by a null character \0. Since you can't assign arrays in C, you can't assign strings either. The literal "hello" is syntactic sugar for const char x[] = {'h','e','l','l','o','\0'};

The correct way would be:

char s[100];
strncpy(s, "hello", 100);

or better yet:

#define STRMAX 100
char    s[STRMAX];
size_t  len;
len = strncpy(s, "hello", STRMAX);

When initializing an array, C allows you to fill it with values. So

char s[100] = "abcd";

is basically the same as

int s[3] = { 1, 2, 3 };

but it doesn't allow you to do the assignment since s is an array and not a free pointer. The meaning of

s = "abcd"

is to assign the pointer value of abcd to s but you can't change s since then nothing will be pointing to the array.
This can and does work if s is a char* - a pointer that can point to anything.

If you want to copy the string simple use strcpy.

1    char s[100];
2    s = "hello";

In the example you provided, s is actually initialized at line 1, not line 2. Even though you didn't assign it a value explicitly at this point, the compiler did.

At line 2, you're performing an assignment operation, and you cannot assign one array of characters to another array of characters like this. You'll have to use strcpy() or some kind of loop to assign each element of the array.

To expand on Sparr's answer

Initialization and assignment are two distinct operations that happen to use the same operator ("=") here.

Think of it like this:

Imagine that there are 2 functions, called InitializeObject, and AssignObject. When the compiler sees thing = value, it looks at the context and calls one InitializeObject if you're making a new thing. If you're not, it instead calls AssignObject.

Normally this is fine as InitializeObject and AssignObject usually behave the same way. Except when dealing with char arrays (and a few other edge cases) in which case they behave differently. Why do this? Well that's a whole other post involving the stack vs the heap and so on and so forth.

PS: As an aside, thinking of it in this way will also help you understand copy constructors and other such things if you ever venture into C++

Note that you can still do:

s[0] = 'h';
s[1] = 'e';
s[2] = 'l';
s[3] = 'l';
s[4] = 'o';
s[5] = '\0';

What I would use is

char *s = "abcd";

You can use this:

yylval.sval=strdup("VHDL + Volcal trance...");

Where yylval is char*. strdup from does the job.

I know that this has already been answered, but I wanted to share an answer that I gave to someone who asked a very similar question on a C/C++ Facebook group.


Arrays don't have assignment operator functions*. This means that you cannot simply assign a char array to a string literal. Why? Because the array itself doesn't have any assignment operator. (*It's a const pointer which can't be changed.)

arrays are simply an area of contiguous allocated memory and the name of the array is actually a pointer to the first element of the array. (Quote from https://www.quora.com/Can-we-copy-an-array-using-an-assignment-operator)

To copy a string literal (such as "Hello world" or "abcd") to your char array, you must manually copy all char elements of the string literal onto the array.

char s[100]; This will initialize an empty array of length 100.

Now to copy your string literal onto this array, use strcpy

strcpy(s, "abcd"); This will copy the contents from the string literal "abcd" and copy it to the s[100] array.

Here's a great example of what it's doing:

int i = 0; //start at 0
do {
s[i] = ("Hello World")[i]; //assign s[i] to the string literal index i
} while(s[i++]); //continue the loop until the last char is null

You should obviously use strcpy instead of this custom string literal copier, but it's a good example that explains how strcpy fundamentally works.

Hope this helps!

I am annoyed by this... It really would be logical if:

char string[10] = "hello";

should give the same result as:

char string[10] = {0};
string = "hello";        // doesn't work!

But I guess it just doesn't work like that. Anyways, here was my workaround:

char string[10] = {0};
sprintf(string,"hello");

its almost as good, because it is short.

Strangely enough, another thing which has worked for me (though a little off-topic perhaps) is when you declare arrays of structs, you can initialize them with the good-ole double quotes like this:

struct myStruct {
char name[NAX_NAME_LEN];
};


struct myStruct name[DATA_ARRAY_SIZE];


name[1] = (struct myStruct ) { "Hello" };

Incidentally, this method of initialization is known as a "compound literal" Id love to see if anyone could explain why this works to use double quotes and not the string = "hello"; way...

This method is great if you have a lot of strings by the way, because it allows you to write code like:

#define DATA_ARRAY_SIZE 4
enum names{ BOB, GEORGE, FRANK, SARAH};
struct myStruct {
char name[NAX_NAME_LEN];
};
struct myStruct name[DATA_ARRAY_SIZE];


name[BOB   ] = (struct myStruct ) { "Bob" };
name[GEORGE] = (struct myStruct ) { "George" };
name[FRANK ] = (struct myStruct ) { "Frank" };
name[SARAH ] = (struct myStruct ) { "Sarah" };

Or if you're going to go all multilingual for some app:

#define NUM_LANGUAGES 4
enum languages{ ENGLISH , FRENCH  , SWEDISH , ITALIAN };
struct myStruct {
char intro[NAX_NAME_LEN];


};
struct myStruct name[DATA_ARRAY_SIZE];


intro[ENGLISH ] = (struct myStruct ) { "Hello" };
intro[FRENCH  ] = (struct myStruct ) { "Bonjour" };
intro[SWEDISH ] = (struct myStruct ) { "Hej" };
intro[ITALIAN ] = (struct myStruct ) { "Ciao" };