c - 为什么不能重新分配字符串数组,但是字符串指针可以使用C语言?

标签 c pointers

char str1[ ] = "Hello" ; 
char str2[10] ; 
char *s = "Hey" ; 
char *q ;
str2 = str1 ; /* error */ 
q = s ; /* works */ 

是C语言中的某种内在属性,还是有某种原因?
如果不能分配数组,为什么可以分配包含数组的结构?

最佳答案

无法分配数组有两个原因:
因为C语言的设计者担心它会太低效。
因为根据C的规则,如果你想说“array1=array2”,它实际上会变成“array1=pointer-to-array2”,这就更没有意义了。
现在,再解释一下这两点。
(1)C最初的目标之一是几乎所有的内置操作都转换为一个或两个机器指令任何复杂或昂贵的东西通常都需要显式的函数调用因此,如果要将一个数组复制到另一个数组,必须显式地

memcpy(array1, array2, sizeof(array2));

编译器不愿意为您生成这种潜在的昂贵代码(是的,我知道,结构分配与这个规则是矛盾的。以后再谈。)
(2)C(所谓的“数组和指针之间的等价性”)的一个基本规则是,除了少数例外,当在表达式中提到数组时,会自动获得指向数组第一个元素的指针。也就是说,如果你说
int a[10];
int *p;

p = a;

赋值“p = a”不是类型不匹配,它的作用与您编写
p = &a[0];

也就是说,p接收指向a第一个元素的指针。
因此,如果试图将一个数组分配给另一个数组:
int a1[10], a2[10];
a1 = a2;             /* wrong */

就好像你说过
a1 = &a2[0];         /* also wrong */

这没有任何意义。
最后,结构呢?您可以将一个结构分配给另一个结构,这通常涉及复制N个字节,这是一种潜在的昂贵操作,我声称当您键入的只是一个分配运算符“=”时,C不愿意执行这种操作。这确实是一个例外,一个矛盾;这在C语言中有点内部矛盾。事情是这样发生的。
我敢肯定C的第一个版本(也就是里奇最初的PDP-11 C编译器的第一个版本)根本没有结构然后,当第一次添加结构时,它们有一个限制:您不能分配它们,或者将它们传递给函数,或者从函数返回它们(这些限制使结构变得不那么有用,但它们在保持编译器简单的上下文中是有意义的,并且不会让编译器在背后生成昂贵的代码。)然后,甚至在稍后,这些限制被删除:结构赋值(以及传递和返回)都被添加(这一切都是很久以前的事了,在公元前的黎明,如果我没记错的话,K&R书的第一个版本说,限制将“很快取消”,一个支持它们的编译器版本在这本书登陆书店的同时问世。)
如果您想为这种矛盾道歉,可以指出结构通常很小(这意味着它们通常可以使用一些指令分配),而数组可以任意大。但是,同样,即使你想通过添加数组赋值来扩展语言,你也不能,因为原因2。
人们常说数组类型是C语言中的“二等公民”,这意味着你不能给它们赋值,也不能把它们传递或返回给函数此外,这永远无法解决(不能解放它们的二级状态),因为已经有了一个定义,定义了当您试图分配数组、将其传递给函数或从函数返回时会发生什么:在所有情况下,您最终只操作指向数组第一个元素的指针。
(我认为多年来有人试图添加数组赋值作为扩展,使用一些特殊语法来“关闭”指针等价规则我不记得他们是怎么工作的,但我想他们中没有一个能被人接受,更别提成为标准了。)
两个脚注:
[1]由于可以分配结构,因此可以通过将数组包装到结构中,诱使编译器为您执行数组分配例如:
struct array_as_struct { int a[10]; };
struct array_as_struct s1, s2;
s1.a[0] = 10;
s1.a[1] = 20;
s2 = s1;

这是完全合法的;你绝对可以逃脱这个“把戏”;即使结构碰巧包含一个数组,你也绝对可以应用分配结构的规则。
[2]在过去,不能将结构传递给函数是库函数如asctime接受指针(如localtime函数返回指针)的原因之一这些函数的定义一直持续到今天。

关于c - 为什么不能重新分配字符串数组,但是字符串指针可以使用C语言?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41922623/

相关文章:

c - 如何清理C中分配的内存?

c - 指针困惑

c++ - 为什么 const QString& param 返回指向数据的错误 const char* 指针

剪掉一段字符串

代码片段警告 : cast to pointer from integer of different size

c - 指针初始化和两个指针指向同一个地址

c - CLOCK_REALTIME有什么用?

c++ - Pascal 的 readkey 有等价物吗?在 C 或 C++ 中?

检查从 aaa..a 到 zzz..z 的每个 "word"

c++ - `extern "C"`是函数类型的一部分吗?