Dan*_*Dan 10 c arrays pointers
#include<stdio.h>
int main(){
int a[] = {1,2,3};
int b[] = {4,5,6};
b = a;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
结果出现这个错误:
array type 'int [3]' is not assignable
Run Code Online (Sandbox Code Playgroud)
我知道数组是左值并且不可分配,但在这种情况下,编译器所要做的就是重新分配指针。b应该只指向 的地址a。为什么这不可行?
Rob*_*rtS 10
“我知道数组是左值并且不可分配,但在这种情况下,编译器所要做的就是重新分配指针。”
“
b应该只指向 的地址a。为什么这不可行?”
你似乎在这里混淆了一些东西。b不是一个指针。它是一个包含三个元素的数组int。
b = a;
Run Code Online (Sandbox Code Playgroud)
由于b此处在赋值中用作左值,因此它被视为类型int [3],而不是int *。指向衰减规则的指针在这里不占位置b,仅适用于a作为右值。
您不能通过在 C 中使用指向b另一个数组(此处)的第一个元素的指针来分配一个数组(此处)。ab = a;
语法不允许这样做。
这就是错误所在
“数组类型‘int [3]’不可赋值”
是对你说的b。
此外,您似乎还误解了指向衰减规则的指针意味着数组无论如何都会转换为指针对象,它可以以任何方式存储不同对象的位置地址。
这不是真的。这种转换仅以一种非常隐式的方式发生,并且是这个问题的主题:
如果要将数组中的值分配a给数组b,可以使用memcpy():
memcpy(b, a, sizeof(a));
Run Code Online (Sandbox Code Playgroud)
我知道数组是左值并且不可分配,但在这种情况下,编译器所要做的就是重新分配指针。
b应该只指向 的地址a。为什么这不可行?
因为b不是指针。当您声明并分配a和时b,您将得到以下结果:
+---+
| 1 | a[0]
+---+
| 2 | a[1]
+---+
| 3 | a[2]
+---+
...
+---+
| 4 | b[0]
+---+
| 5 | b[1]
+---+
| 6 | b[2]
+---+
Run Code Online (Sandbox Code Playgroud)
没有为任何指针留出空间。没有指针对象a或b与数组元素本身分开。
C 源自一种称为 B 的早期语言,在 B 中,有一个指向第一个元素的单独指针:
+---+
b: | +-+--+
+---+ |
... |
+----+
|
V
+---+
| | b[0]
+---+
| | b[1]
+---+
...
+---+
| | b[N-1]
+---+
Run Code Online (Sandbox Code Playgroud)
当 Dennis Ritchie 开发 C 时,他想保留 B 的数组语义(具体来说,a[i] == *(a + i)),但他不想在任何地方存储该单独的指针。因此,他创建了以下规则 - 除非它是 thesizeof或一元运算符的操作数&,或者是用于在声明中初始化字符数组的字符串文字,否则类型为“N-element array of ”的表达式T将被转换(“衰减”)到“指针”类型的表达式T,并且表达式的值将是数组第一个元素的地址,并且该值不是左值。
这有几个实际影响,其中最相关的是数组表达式可能不是赋值的目标。在大多数情况下,数组表达式会失去其“数组性”,并且不会像其他类型一样进行处理。
编辑
实际上,这错误地表述了情况 - 数组表达式可能不是赋值的目标,因为数组表达式不是可修改的左值。衰变规则不起作用。但“数组不像其他类型一样被对待”这句话仍然成立。
结束编辑
结果是您无法仅使用=运算符将一个数组的内容复制到另一个数组。您必须使用库函数(例如)memcpy或单独复制每个元素。
Others already explained what you got wrong. I'm writing that answer to explain that actually the compiler could assign an array to another, and you can achieve the same effect with minimal change to your sample code.
Just wrap your array in a structure.
#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;
}
Run Code Online (Sandbox Code Playgroud)
Once the array is wrapped in a structure copying the array member of the structure works exactly as copying any other member. In other words you are copying an array. This trick is usefull in some cases like when you really want to pass an array to a function by copying it. It's slightly cleaner and safer than using memcopy for that purpose, which obviously would also work.
Henceforth the reason why it is not allowed for top level arrays is not because the compiler can't do it, but merely because that's not what most programmers usually wants to do.
Usually they just want to decay the array to a pointer. Obviously that is what you thought it should do, and direct copy of array is likely forbiden to avoid specifically that misunderstanding.