34

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

int main(void) {

char s[4];

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

return 0;
}

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

4

4 回答 4

34

C 中的数组是不可赋值且不可复制初始化的。这就是数组在 C 中的样子。从历史上看,在值上下文中(在赋值的 RHS 上)数组衰减为指针,这就是正式阻止赋值和复制初始化的原因。这适用于所有数组,而不仅仅是char数组。

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

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

char c[] = "abc";

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

这意味着无论何时您想要复制一个裸(非包装)数组,您都必须使用库级别的内存复制函数,例如memcpy. strcpy只是专门为使用字符串而量身定制的一种风格。

于 2011-08-01T16:02:34.217 回答
14

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

char *p;
p = "abc";

顺便说一句,有一个C FAQ

数组是 C 中的“二等公民”;这种偏见的一个结果是你不能分配给他们

于 2011-08-01T16:00:36.030 回答
3

简短的回答:历史原因。C 从来没有内置的字符串类型。直到 C++ 出现,std::string 才出现,甚至在最初的实现中也没有出现

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

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

于 2011-08-01T16:02:41.287 回答
0

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

除了字符串字面量之外,零结尾的字符串几乎在所有用途上都不如其他形式但字面量是许多程序必须处理的最常见的字符串形式,因此拥有库函数具有相当大的优势有效地处理它们;然后,在它们不太理想的情况下使用以零结尾的字符串比为其他类型拥有一组单独的库例程变得更容易。

于 2017-05-01T19:04:09.750 回答