简体   繁体   English

为什么我们不能将新字符串分配给 char 数组,而是分配给指针?

[英]Why can´t we assign a new string to an char array, but to a pointer?

i was trying to reassign a string to a pre-initialized array a[], and all i could get was an error我试图将一个字符串重新分配给一个预先初始化的数组 a[],但我得到的只是一个错误

main()
{
    char a[] = "Sunstroke";
    char *b = "Coldwave";

    a = "Coldwave";
    b = "Sunstroke";
    printf("\n %s %s",a,b);
}

[Error]: incompatible types when assigning to type 'char[10]' from type 'char *'.. i searched for this but was unable to find any reason.. i also tried to re-assign it by redeclaration like [错误]:从类型 'char *' 分配到类型 'char[10]' 时类型不兼容。

char a[] = "Sunstroke";

but it didnt worked...但它没有用...

but in case of a pointer it was possible as in above program..但是在指针的情况下,就像上面的程序一样..

To understand what's going on here, two language rules are important:要了解这里发生了什么,有两个语言规则很重要:

  • Arrays are not assignable.数组不可分配。
  • An array can be converted to a pointer to its first element.数组可以转换为指向其第一个元素的指针。

It's also important to understand what a string literal like "Sunstroke" is.了解像"Sunstroke"这样的字符串文字是什么也很重要。 It's a static array of constant characters, large enough to hold all the characters of a string with a terminator at the end.它是一个常量字符的静态数组,大到足以容纳以终止符结尾的字符串的所有字符。 So in this case, it's a const char[10] array, containing the nine characters followed by the zero-valued terminator.所以在这种情况下,它是一个const char[10]数组,包含九个字符,后跟零值终止符。 Being static , the array is stored somewhere in memory for the lifetime of the program.作为static ,数组在程序的生命周期内存储在内存中的某处。

char a[] = "Sunstroke";

This creates a local array, and initialises it by copying the characters from the string literal.这将创建一个本地数组,并通过从字符串文字中复制字符来初始化它。

char *b = "Coldwave";

This creates a pointer, and initialises it to point to the literal itself.这将创建一个指针,并将其初始化为指向文字本身。 Note that this is dangerous: the literal is const , but the pointer isn't, so you can write code that attempts to modify the literal, giving undefined behaviour.请注意,这是危险的:文字是const ,但指针不是,因此您可以编写尝试修改文字的代码,从而给出未定义的行为。 This conversion is deprecated (certainly in C++, I'm not sure about C), so the compiler should give you a warning.这种转换已被弃用(当然在 C++ 中,我不确定 C),因此编译器应该给你一个警告。 You have enabled all the compiler warnings you can, haven't you?您已经启用了所有可能的编译器警告,不是吗?

a = "Coldwave";

This attempts to reassign the array, but fails because arrays aren't assignable.这会尝试重新分配数组,但由于数组不可分配而失败。 There's no particularly good reason why they aren't;没有特别好的理由为什么他们不是。 that's just the way the languages evolved.这就是语言进化的方式。

b = "Sunstroke";

This reassigns the pointer to point to a different literal.这会重新分配指针以指向不同的文字。 That's fine (apart from the lack of const noted above).这很好(除了上面提到的缺少const之外)。

If you need to manipulate strings, then:如果您需要操作字符串,则:

  • in C you'll need to carefully create arrays large enough for your needs, and use the library functions in <string.h> (or your own handcrafted code) to manipulate the characters in those arrays;在 C 中,您需要仔细创建足够大的数组以满足您的需要,并使用<string.h>的库函数(或您自己编写的代码)来操作这些数组中的字符;
  • in C++, use the std::string class to handle memory management, assignment, etc. for you.在 C++ 中,使用std::string类为您处理内存管理、分配等。

Hard-coded string literals such as "Coldwave" are actually char[] (char array) types -- but it is undefined behavior to modify them ( C99 :6.4.5.6).诸如“Coldwave”之类的硬编码字符串文字实际上是char[] (字符数组)类型——但修改它们是未定义的行为C99 :6.4.5.6)。 Note that below, however, b is still a char* (char pointer):但是请注意,下面的b仍然是一个char* (字符指针):

char *b = "Coldwave";

To which a char[] has been assigned.已为其分配了char[] That's okay.没关系。 It is different than this though:但它与此不同:

char a[] = "Coldwave";

Which is an initialization of a char[] .这是char[]初始化 You can only initialize a variable once, when it is declared, and initialization is the only circumstance in which you can populate an array or other compound type (such as a struct) via assignment like this.您只能在声明变量时初始化一次,并且初始化是您可以通过这样的赋值填充数组或其他复合类型(例如结构)的唯一情况。 You could not do this, however:但是,您不能这样做:

char c[] = a;

Because when used on the right hand side of an assignment, array variables function as pointers to the array they represent, which is why char *b = a works.因为当在赋值的右侧使用时,数组变量充当指向它们所代表的数组的指针,这就是char *b = a起作用的原因。

So the reason you can't do this with the variables from above:所以你不能用上面的变量做到这一点的原因:

a = b;
// or
a = "Sunstroke";

Is because that would be assigning a char* to a char[] -- no good;是因为那会将char*分配给char[] —— 不好; you can only do it the other way around.你只能反过来做。

In the case of C if we look at c99 draft standard section 6.5.16 Assignment operators paragraph 2 says:C的情况下,如果我们查看c99 草案标准6.5.16赋值运算符2段说:

An assignment operator shall have a modifiable lvalue as its left operand.赋值运算符应有一个可修改的左值作为其左操作数。

and section 6.3.2.1 Lvalues, arrays, and function designators paragraph 1 says:和第6.3.2.1左值、数组和函数指示符1段说:

[...]A modifiable lvalue is an lvalue that does not have array type[...] [...]可修改的左值是没有数组类型的左值[...]

So since arrays are not modifiable lvalues you can not assign to them.因此,由于数组不是可修改的左值,因此您无法分配给它们。 As for initialization section 6.7.8 Initialization paragraph 14 says:至于初始化部分6.7.8初始化14段说:

An array of character type may be initialized by a character string literal[...]字符类型的数组可以由字符串文字[...]

In the C++ draft standard the relevant sections are 4.2 Array-to-pointer conversion paragraph 1 which says:C++ 草案标准中,相关部分是4.2 Array-to-pointer conversion1段,它说:

An lvalue or rvalue of type “array of NT” or “array of unknown bound of T” can be converted to a prvalue of type “pointer to T”. “NT 数组”或“T 的未知边界数组”类型的左值或右值可以转换为“指向 T 的指针”类型的纯右值。 The result is a pointer to the first element of the array.结果是指向数组第一个元素的指针。

a prvalue is a pure rvalue and section 5.17 Assignment and compound assignment operators paragraph 1 which says: prvalue是纯右值,第5.17赋值和复合赋值运算符1段说:

[...]All require a modifiable lvalue as their left operand[...] [...]都需要一个可修改的左值作为它们的左操作数[...]

Let me simplify the program to:让我将程序简化为:

char a[] = "Sunstroke";
char *b = a;

Assume that the address of a is 100, then in memory, it looks like this (illustrating only the size of pointer and endian-ness etc. may vary):假设a的地址是100,那么在内存中,它看起来是这样的(仅说明指针大小和字节序等可能会有所不同):

[S] [u] [n] [s] [t] [r] [o] [k] [e] [\0]         ...       [0] [0] [0] [100]
100 101 102 103 104 105 106 107 108 109                           200
 ^                                                                 ^
 |                                                                 |
 a                                                                 b

As long as the life cycle of the array, a will always be the same place, you can't modify it.只要数组的生命周期, a永远是同一个地方,你不能修改它。

b , on the other hand, is a pointer that contains the address of the array, you can modify the value of b to point to other places. b ,另一方面,是一个包含数组地址的指针,你可以修改b的值指向其他地方。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么我们不能将字符串值赋给2d char数组? - why we can't assign a string value to 2d char array? 为什么我们不能直接将 arr 分配给指向数组的指针 - Why can't we directly assign arr to pointer to array 为什么我们不能将字符串复制到字符指针何时我们可以直接为其指定字符串? - Why Can't we copy a string to Character Pointer WHEN we can assign a string directly to it? 无法使用 char 指针打印字符串数组 - Can't print a string array with a char pointer 为什么我们不能直接将二维数组的地址分配给指针? - Why can't we directly assign the address of a 2D array to a pointer? 为什么可以将字符串分配给char *指针,而不是char []数组? - Why can a string be assigned to a char* pointer, but not to a char[] array? 在 C 中,为什么不能在声明后将字符串分配给 char 数组? - In C, why can't I assign a string to a char array after it's declared? 无法将char值分配给struct中的指针 - Can't assign char value to pointer in struct 为什么我们可以将整数分配给char变量 - Why can we assign integers to a char variable 为什么我能够像这样将新字符串重新分配给 C 中的 char 指针(ch *string = “hello”; string = “assign”;) - Why am I able to re-assign a new string to a char pointer in C like so ( ch *string = “hello”; string = “assign”;)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM