int a[10];
int b[10];
a = b; // illegal
typedef struct {
int real;
int imag;
} complex;
complex c,d;
c = d; //legal
[我意识到a和b是第一种情况下的地址,但是第二种情况下的符号]
答案 0 :(得分:6)
对于历史信息,这可能很有趣:http://cm.bell-labs.com/who/dmr/chist.html
在B中,声明一个数组会为数组留出内存,就像C一样,但是为变量提供的名称用于定义指向数组的指针。 Ritchie在C中对此进行了更改,因此名称“是”数组,但在使用时可以衰减为指针:
在今天的C中存活的规则是数组类型的值 当它们出现在表达式中时转换为指向的表达式 构成阵列的第一个对象。
本发明使大多数现有B代码能够继续工作, 尽管语言的语义发生了根本性的转变。少数 将新值分配给数组名称以调整其值的程序 原点 - 可能在B和BCPL中,在C中无意义 - 很容易修复。
如果在那个早期阶段,Ritchie已经定义了a = b
来复制数组,那么他试图从B端口移植到C的代码就不会那么容易修复了。正如他所定义的那样,该代码会产生错误,他可以修复它。如果他让C复制数组,那么他就会默默地改变代码的含义来复制数组,而不是重新设置用于访问数组的名称。
还有一个问题,“为什么自40年以来没有添加这个功能”,但我认为这就是为什么它不是从那里开始的。这本来是努力实现的,而且这种努力实际上会使C 的早期版本更糟糕,因为稍微难以将B和BCPL代码移植到C.所以当然Ritchie没有不行。
答案 1 :(得分:4)
因为C说你不能,它说“可修改的左值是一个没有数组类型的左值, 没有不完整的类型“,因此无法将数组分配给。
此外,
在a = b;
等值上下文中使用数组名称时,名称a
和b
均表示
&a[0]
和&b[0]
。通常称为数组“衰减”到指针。
但是,数组不是指针,因此尝试使用指针分配数组是没有意义的。
答案 2 :(得分:3)
主要原因当然是标准。在赋值运算符约束上,它说:
(C99,6.5.16p2)“赋值运算符应具有可修改的左值作为其左操作数”
它将可修改的左值定义为
(C99,6.3.2.1p1)“可修改的左值是一个没有数组类型的左值,[...]”。
因此不允许分配给数组。
但主要原因是历史原因,因为阵列副本被认为不适合硬件(旧的PDP系统)。在C的第一个版本中也不是这样,也不允许分配结构类型对象。它后来被添加到语言中,但是对于数组而言,需要更改该语言的许多部分以允许分配给数组。
答案 3 :(得分:3)
首先要理解的是数组不是指针。阅读comp.lang.c FAQ的第6部分。我等一下。
...
好的,完成了?不,回去看看整件事。
...
太好了,谢谢。
一般来说,C中的数组是二等公民。有数组类型,数组对象,甚至数组值,但数组几乎总是通过指向其元素的指针来操作。
这需要程序员多做一些工作(正如您所见,您不能只分配数组),但它也为您提供了更大的灵活性。处理数组的程序通常需要处理不同大小的数组,甚至是在执行时间之前无法确定的大小。即使允许数组赋值,10个int
的数组和20个int
的数组也是不同且不兼容的类型。如果你有一个固定大小的数组,就像在你的问题中的代码那样,通常只有一些元素当前是相关的;你可能有一个10元素的数组,但你目前只使用前5个元素。逐个元素处理这样的数组使得更容易只处理当前活动的元素(你必须跟踪自己的事物)。
另一方面,对于结构,在定义类型时确定成员的数量和类型。你不能通过推进指针来遍历结构的成员,就像对数组一样,因为成员通常是不同类型的。数组和结构是不同的东西,它们具有对它们有意义的不同操作集。
该语言中有一些规则试图使其更容易实现,即:
&
(地址)运算符的操作数时; sizeof
的操作数时;和int func(char s[]);
中已调整指向参数:int func(char *s);
。(有人可能会说这些规则引起的混淆比他们预防的更多,但这就是定义语言的方式。)
现在我认为语言可以已经定义,或者可以重新定义,以便在有意义的情况下允许数组赋值:
int a[10];
int b[10];
/* ... */
a = b; /* Why not? */.
也许这样的改变甚至可以在不破坏现有代码的情况下进行。但这需要另一个特殊情况用于数组到指针转换规则。它只适用于a
和b
等固定大小的数组,尽管它们在介绍性编程练习中非常常见,但在生产代码中并不常见。
答案 4 :(得分:-1)
数组名称是一个const指针,因此您无法更改它指向的内容。
假设你的意思是最后一行的c = d是合法的,它只是将一个非const变量复制到另一个非const变量,这是完全合法的。
答案 5 :(得分:-1)
a实际上是数组第一个元素的“指针”,它是一个常量“指针”, 所以你试图指定一个l-“指针”。
你可以通过以下方式实现目标:
struct arraystruct
{
int t[10];
};
struct arraystruct a,b;
a=b;
编辑:我忘了提到有一些例外,其中数组不应被视为指针:
- 您可以使用sizeof(数组),但不能使用sizeof(指针)
-array of literal string
-a和& a是相同的
答案 6 :(得分:-2)
这是因为您使用的数组类型是所谓的静态数组,即。它的内存在堆栈上。 如果你使用动态数组(带指针)你的任务是合法的(但是内存泄漏是可能的)。这将是一个浅薄的副本。