C - 为什么 strcpy() 是必要的
有人可以向我解释一下为什么需要 strcpy() 将字符串分配给字符数组,例如下面的代码片段。
int main(void) {
char s[4];
s = "abc"; //Fails
strcpy(s, "abc"); //Succeeds
return 0;
}
s = "abc"
失败的原因是什么?为什么 strcpy() 是在声明字符串后将字符串分配给 char 数组的唯一方法?对我来说,你必须使用函数来执行基本任务似乎很奇怪。
Can someone please explain to me why strcpy() is necessary to assign strings to character arrays, such as in the following code snippet.
int main(void) {
char s[4];
s = "abc"; //Fails
strcpy(s, "abc"); //Succeeds
return 0;
}
What is the reason that s = "abc"
fails? And why is strcpy() the only way to assign strings to char arrays after they have been declared? It seems strange to me that you have to use a function to carry out a basic assignment.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
C 中的数组是不可赋值且不可复制初始化的。这就是数组在 C 中的样子。从历史上看,在值上下文(在赋值的右侧)中,数组衰减为指针,这就是形式上阻止赋值和复制初始化的原因。这适用于所有数组,而不仅仅是
char
数组。C 语言从其前身 B 和 BCPL 语言继承了这种数组行为。在这些语言中,数组由物理指针表示。 (显然,当您将一个数组分配给另一个数组时,指针的重新分配并不是您希望发生的情况。)在 C 语言中,数组不是指针,但它们确实通过衰减来“模拟”B 和 BCPL 数组的历史行为大多数情况下指向指针。这一历史遗留问题使得 C 数组至今仍不可复制。
上面的一个例外是使用字符串文字进行初始化。即,您可以
在概念上将字符串文字
"abc"
复制到数组c
中。另一个例外是数组包装到结构类型中,当复制整个结构对象时,也会复制该结构类型。就是这样。这意味着每当您想要复制裸(非包装)数组时,您都必须使用库级内存复制函数,例如memcpy。
strcpy
只是专门为处理字符串而定制的一种风格。Arrays in C are non-assignable and non-copy-initializable. That's just how arrays are in C. Historically, in value context (on the RHS of assignment) arrays decay to pointers, which is what formally prevents assignment and copy-initialization. This applies to all arrays, not only to
char
arrays.C language inherits this arrays behavior from its predecessors - B and BCPL languages. In those languages arrays were represented by physical pointers. (And obviously re-assignment of pointers is not what you'd want to happen when you assign one array to another.) In C language arrays are not pointers, yet they do "simulate" the historical behavior of B and BCPL arrays by decaying to pointers in most cases. This historical legacy is what keeps C arrays non-copyable to this day.
One exception from the above is the initialization with a string literal. I.e. you can do
in which case conceptually we are copying string literal
"abc"
to arrayc
. Another exception is array wrapped into a struct type, which is copied when the whole struct object is copied. And that's about it.This means that whenever you want to copy a naked (non-wrapped) array, you have to use a library-level memory copying function, like
memcpy
.strcpy
is just a flavor of that specifically tailored to work with strings.这就是 C 中的数组。你不能给它们赋值。如果愿意,您可以使用指针:
顺便说一句,有一个 C FAQ。
That's simply what arrays are in C. You can't assign to them. You can use pointers if you like:
Incidentally, there is a C FAQ.
简短的回答:历史原因。 C 从来没有内置的字符串类型。直到 C++ 出现后,std::string 才应运而生,即使如此,第一个实现也没有出现。
长答案:“abc”的类型不是
char[]
,而是而是char *
。strcpy
是一种机制,您可以使用它复制指针指向的数据(在本例中为 ABC)。strcpy
并不是初始化数组的唯一方法,但是,它足够智能,可以检测并尊重字符串末尾的终止 0。您还可以使用 memcpy 将字符串复制到 s 中,但这需要您传入要复制的数据的长度,并确保终止 0 (NULL)存在于s
中Short answer: historical reasons. C never had a built in string type. It wasn't until C++ came along that std::string came into being, and even that did not arrive with the first implementations
Long answer: the type of "abc" is not
char[]
, but ratherchar *
.strcpy
is one mechanism with which you can copy the data that the pointer points at (in this case that's ABC).strcpy
isn't the only way to initialize an array, however, it is smart enough to detect and respect the terminating 0 at the end of the string. You could also usememcpy
to copy the string intos
but that requires you pass in the length of the data to be copied, and to ensure the terminating 0 (NULL) is present ins
C 语言缺乏任何方便的语法来获取指向字符串文字的指针及其长度指示。一些语言(包括许多 Pascal 方言)在每个字符串前添加一个报告其长度的字节;这对于许多用途来说都很有效,但将字符串文字限制为 255 个字符。 C 的方法允许容纳任意长度的字符串文字,但无论长度如何,仅增加一个字节的开销。
除了字符串文字之外,零终止字符串几乎在所有用途上都比其他形式差,但文字无疑是许多程序必须处理的最常见的字符串形式,因此有让库函数有效地处理它们具有相当大的优势;然后,在不太理想的情况下使用零终止字符串变得比为其他类型使用一组单独的库例程更容易。
The C language lacks any convenient syntax for getting a pointer to a string literal along with an indication of its length. Some languages including many Pascal dialects prefix each string with a byte reporting its length; this works nicely for many purposes, but limits string literals to 255 characters. C's approach allows string literals of any length to be accommodated, but adds only a single byte of overhead regardless of length.
Zero-terminated strings are inferior to other forms for almost every purpose other than string literals, but literals are so far and away the most common form of string that many programs will have to deal with, and thus there is considerable advantage to having library functions deal with them effectively; it then becomes easier to use zero-terminated strings in cases where they are less than ideal than to have a separate set of library routines for other types.