[英]Why can't I assign an array to another array in C
#include<stdio.h>
int main(){
int a[] = {1,2,3};
int b[] = {4,5,6};
b = a;
return 0;
}
导致此错误:
array type 'int [3]' is not assignable
我知道 arrays 是左值并且不可分配,但在这种情况下,编译器所要做的就是重新分配一个指针。 b
应该只指向a
的地址。 为什么这不可行?
“我知道 arrays 是左值并且不可分配,但在这种情况下,编译器所要做的就是重新分配一个指针。”
“
b
应该只指向a
的地址。为什么这不可行?”
你似乎在这里混淆了一些东西。 b
不是指针。 它是一个由三个int
元素组成的数组。
b = a;
由于b
在这里用作赋值中的左值,因此它被视为int [3]
类型,而不是int *
。 对于b
,指向衰减规则的指针在此处没有任何位置,仅对于a
作为右值。
您不能使用b = a;
通过指向另一个数组(此处a
)的第一个元素的指针来分配数组(此处为b
) 在 C 中。
语法不允许这样做。
这就是错误
“数组类型‘int [3]’不可赋值”
对你说b
。
此外,您似乎误解了指向衰减规则的指针意味着无论如何将数组转换为指针object ,它可以以任何方式存储不同对象的位置地址。
这不是真的。 这种转换只是以一种非常隐含的方式发生,并且是这个 SO 问题的主题:
如果要将数组a
中的值分配给数组b
,可以使用memcpy()
:
memcpy(b, a, sizeof(a));
我知道 arrays 是左值并且不可分配,但在这种情况下,编译器所要做的就是重新分配一个指针。
b
应该只指向a
的地址。 为什么这不可行?
因为b
不是指针。 当您声明和分配a
和b
时,您会得到:
+---+
| 1 | a[0]
+---+
| 2 | a[1]
+---+
| 3 | a[2]
+---+
...
+---+
| 4 | b[0]
+---+
| 5 | b[1]
+---+
| 6 | b[2]
+---+
没有为任何指针留出空间。 没有指针 object a
或b
与数组元素本身分开。
C 派生自早期的语言 B,在 B 中有一个单独的指向第一个元素的指针:
+---+
b: | +-+--+
+---+ |
... |
+----+
|
V
+---+
| | b[0]
+---+
| | b[1]
+---+
...
+---+
| | b[N-1]
+---+
当 Dennis Ritchie 开发 C 时,他想保留 B 的数组语义(特别是a[i] == *(a + i)
),但他不想将那个单独的指针存储在任何地方。 因此,他创建了以下规则 - 除非它是sizeof
或一元&
运算符的操作数,或者是用于在声明中初始化字符数组的字符串文字,否则“ T
的 N 元素数组”类型的表达式将是转换(“decay”)为“pointer to T
”类型的表达式,表达式的值将是数组第一个元素的地址,并且该值不是左值。
这有几个实际效果,这里最相关的是数组表达式可能不是赋值的目标。 在大多数情况下,数组表达式失去了它们的“数组特性”,并且根本不像其他类型那样被对待。
编辑
实际上,这是错误的情况——数组表达式可能不是赋值的目标,因为数组表达式不是可修改的左值。 衰减规则不起作用。 但是“数组不像其他类型一样对待”的说法仍然成立。
结束编辑
结果是您不能仅使用=
运算符将一个数组的内容复制到另一个数组。 您必须使用类似memcpy
的库 function 或单独复制每个元素。
其他人已经解释了你错了什么。 我写这个答案是为了解释实际上编译器可以将一个数组分配给另一个数组,并且您可以通过对示例代码的最小更改来实现相同的效果。
只需将您的数组包装在一个结构中。
#include <stdio.h>
int main(){
struct Array3 {
int t[3];
};
struct Array3 a = {{1,2,3}};
struct Array3 b = {{4,5,6}};
a = b;
printf("%d %d %d", a.t[0], a.t[1], a.t[2]);
return 0;
}
一旦数组被包装在一个结构中,复制该结构的数组成员就像复制任何其他成员一样工作。 换句话说,您正在复制一个数组。 这个技巧在某些情况下很有用,比如当你真的想通过复制将数组传递给 function 时。 它比为此目的使用 memcopy 稍微清洁和安全,显然也可以。
此后不允许顶级 arrays 的原因不是因为编译器不能这样做,而仅仅是因为这不是大多数程序员通常想要做的。
通常他们只想将数组衰减为指针。 显然,这是您认为应该做的事情,并且可能禁止直接复制数组,以避免具体的误解。
代码中的变量b
在堆栈上分配为 3 个连续的int
s。 您可以获取b
的地址并将其存储在int*
类型的变量中。 如果您在堆上分配数组并仅将指向它的指针存储在堆栈上,则可以为其分配一个值,在这种情况下,实际上您可以将指针的值更改为a
.
来自C 编程语言:
数组名是第零个元素的地址。
必须牢记数组名称和指针之间的一个区别。 指针是一个变量。 但是数组名不是变量。
我的理解是数组名是一个常量,所以不能赋值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.