关于字符串:C-为什么必须使用strcpy()

C - why is strcpy() necessary

有人可以向我解释为什么需要strcpy()来将字符串分配给字符数组,例如下面的代码片段。

1
2
3
4
5
6
7
8
9
int main(void) {

char s[4];

s ="abc"; //Fails
strcpy(s,"abc"); //Succeeds

return 0;
}

s ="abc"失败的原因是什么? 为什么在声明字符串后将strcpy()分配给char数组的唯一方法呢? 对于我来说,您必须使用函数来执行基本分配似乎很奇怪。


C中的数组不可分配且不可复制初始化。这就是数组在C语言中的用法。从历史上看,在值上下文中(在赋值RHS上),数组会衰减为指针,这是形式上防止赋值和复制初始化的原因。这适用于所有阵列,不仅适用于char阵列。

C语言从其前身B和BCPL语言继承了此数组的行为。在那些语言中,数组由物理指针表示。 (显然,当将一个数组分配给另一个数组时,指针的重新分配不是您想要的。)在C语言中,数组不是指针,但是它们通过衰减来"模拟" B和BCPL数??组的历史行为。在大多数情况下指向指针。这一历史遗产使C阵列至今不可复制。

上面的一个例外是使用字符串文字进行初始化。即你可以做

1
char c[] ="abc";

在这种情况下,从概念上讲,我们将字符串文字"abc"复制到数组c。另一个例外是包装到结构类型中的数组,复制整个结构对象时将复制该数组。就是这样。

这意味着无论何时要复制裸(非包装)阵列,都必须使用库级别的内存复制功能,例如memcpystrcpy只是专门针对弦乐而设计的一种风格。


这就是C中的数组。您无法分配给它们。如果愿意,可以使用指针:

1
2
char *p;
p ="abc";

附带地,有一个C常见问题解答。

Arrays are ``second-class citizens'' in C; one upshot of this
prejudice is that you cannot assign to them.


简短的答案:历史原因。 C从来没有内置字符串类型。直到C ++出现了std :: string,甚至在第一个实现中都没有实现

长答案:" abc"的类型不是char[],而是char *strcpy是一种机制,您可以使用该机制复制指针指向的数据(在本例中为ABC)。

strcpy不是初始化数组的唯一方法,但是,它足够聪明,可以检测并遵守字符串末尾的终止0。您还可以使用memcpy将字符串复制到s中,但这要求您传入要复制的数据的长度,并确保在s中存在终止符0(NULL)。


C语言缺乏任何方便的语法来获取指向字符串文字的指针及其长度指示。包括许多Pascal方言在内的某些语言在每个字符串前加一个字节来报告其长度。这对于许多目的都很好,但是将字符串文字限制为255个字符。 C的方法允许容纳任意长度的字符串文字,但无论长度如何,都只会增加一个字节的开销。

零终止的字符串在几乎所有目的上都比其他形式都差劲,除了字符串文字,但文字到目前为止是许多程序必须处理的最常见的字符串形式,因此拥有库函数具有相当大的优势有效地处理它们;这样,如果它们不理想,就比使用单独的其他类型的库例程集更容易使用零终止的字符串。