简体   繁体   English

为什么我不能将一个数组分配给 C 中的另一个数组

[英]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;  
 } 

Result in this error:导致此错误:

array type 'int [3]' is not assignable

I know arrays are lvalues and are not assignable but in this case, all the compiler has to do is reassign a pointer.我知道 arrays 是左值并且不可分配,但在这种情况下,编译器所要做的就是重新分配一个指针。 b should just point to the address of a . b应该只指向a的地址。 Why isn't this doable?为什么这不可行?

"I know arrays are lvalues and are not assignable but in this case, all the compiler has to do is reassign a pointer." “我知道 arrays 是左值并且不可分配,但在这种情况下,编译器所要做的就是重新分配一个指针。”

" b should just point to the address of a . Why isn't this doable?" b应该只指向a的地址。为什么这不可行?”

You seem to confuse here something.你似乎在这里混淆了一些东西。 b isn't a pointer . b不是指针 It is an array of three int elements.它是一个由三个int元素组成的数组

b = a;

Since b is used here as lvalue in the assignment, it is taken as of type int [3] , not int * .由于b在这里用作赋值中的左值,因此它被视为int [3]类型,而不是int * The pointer to decay rule takes no place in here for b , only for a as rvalue.对于b ,指向衰减规则的指针在此处没有任何位置,仅对于a作为右值。

You cannot assign an array (here b ) by a pointer to the first element of another array (here a ) by using b = a;您不能使用b = a;通过指向另一个数组(此处a )的第一个元素的指针来分配数组(此处为b in C.在 C 中。

The syntax doesn't allow that.语法不允许这样做。

That's what the error这就是错误

" array type 'int [3]' is not assignable " 数组类型‘int [3]’不可赋值

is saying to you for b .对你说b

Also you seem to be under the misunderstanding that the pointer to decay rule means that an array is anyhow converted to a pointer object , which can in any manner store addresses of locations of different objects.此外,您似乎误解了指向衰减规则的指针意味着无论如何将数组转换为指针object ,它可以以任何方式存储不同对象的位置地址。

This is not true.这不是真的。 This conversion is only happening in a very implicit kind of way and is subject of this SO question:这种转换只是以一种非常隐含的方式发生,并且是这个 SO 问题的主题:

Is the array to pointer decay changed to a pointer object?指向指针衰减的数组是否更改为指针 object?


If you want to assign the values from array a to the array b , you can use memcpy() :如果要将数组a中的值分配给数组b ,可以使用memcpy()

memcpy(b, a, sizeof(a));

I know arrays are lvalues and are not assignable but in this case, all the compiler has to do is reassign a pointer.我知道 arrays 是左值并且不可分配,但在这种情况下,编译器所要做的就是重新分配一个指针。 b should just point to the address of a . b应该只指向a的地址。 Why isn't this doable?为什么这不可行?

Because b isn't a pointer.因为b不是指针。 When you declare and allocate a and b , this is what you get:当您声明和分配ab时,您会得到:

+---+
| 1 | a[0]
+---+
| 2 | a[1]
+---+
| 3 | a[2]
+---+
 ...
+---+
| 4 | b[0]
+---+
| 5 | b[1]
+---+
| 6 | b[2]
+---+

No space is set aside for any pointers.没有为任何指针留出空间。 There is no pointer object a or b separate from the array elements themselves.没有指针 object ab与数组元素本身分开。

C was derived from an earlier language called B, and in B there was a separate pointer to the first element: C 派生自早期的语言 B,在 B 中一个单独的指向第一个元素的指针:

   +---+
b: | +-+--+
   +---+  |
    ...   |
     +----+
     |
     V
   +---+
   |   | b[0]
   +---+
   |   | b[1]
   +---+
    ...
   +---+
   |   | b[N-1]
   +---+

When Dennis Ritchie was developing C, he wanted to keep B's array semantics (specifically, a[i] == *(a + i) ), but he didn't want to store that separate pointer anywhere.当 Dennis Ritchie 开发 C 时,他想保留 B 的数组语义(特别是a[i] == *(a + i) ),但他不想将那个单独的指针存储在任何地方。 So instead he created the following rule - unless it is the operand of the sizeof or unary & operators, or is a string literal used to initialize a character array in a declaration, an expression of type "N-element array of T " will be converted ("decay") to an expression of type "pointer to T " and the value of the expression will be the address of the first element of the array, and that value is not an lvalue .因此,他创建了以下规则 - 除非它是sizeof或一元&运算符的操作数,或者是用于在声明中初始化字符数组的字符串文字,否则“ T的 N 元素数组”类型的表达式将是转换(“decay”)为“pointer to T ”类型的表达式,表达式的值将是数组第一个元素的地址,并且该值不是左值

This has several practical effects, the most relevant here being that an array expression may not be the target of an assignment.这有几个实际效果,这里最相关的是数组表达式可能不是赋值的目标。 Array expressions lose their "array-ness" under most circumstances, and simply are not treated like other types.在大多数情况下,数组表达式失去了它们的“数组特性”,并且根本不像其他类型那样被对待。

Edit编辑

Actually, that misstates the case - array expression may not be the target of an assignment because an array expression is not a modifiable lvalue.实际上,这是错误的情况——数组表达式可能不是赋值的目标,因为数组表达式不是可修改的左值。 The decay rule doesn't come into play.衰减规则不起作用。 But the statement "arrays are not treated like other types" still holds.但是“数组不像其他类型一样对待”的说法仍然成立。

End Edit结束编辑

The upshot is that you cannot copy the contents of one array to the other using just the = operator.结果是您不能仅使用=运算符将一个数组的内容复制到另一个数组。 You must either use a library function like memcpy or copy each element individually.您必须使用类似memcpy的库 function 或单独复制每个元素。

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;
 }

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.这个技巧在某些情况下很有用,比如当你真的想通过复制将数组传递给 function 时。 It's slightly cleaner and safer than using memcopy for that purpose, which obviously would also work.它比为此目的使用 memcopy 稍微清洁和安全,显然也可以。

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.此后不允许顶级 arrays 的原因不是因为编译器不能这样做,而仅仅是因为这不是大多数程序员通常想要做的。

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.显然,这是您认为应该做的事情,并且可能禁止直接复制数组,以避免具体的误解。

The variable b in your code is allocated on the stack as 3 consecutive int s.代码中的变量b在堆栈上分配为 3 个连续的int s。 You can take the address of b and store it in a variable of type int* .您可以获取b的地址并将其存储在int*类型的变量中。 You could assign a value to it if you allocate the array on the heap and store only the pointer to it on the stack, in this case you could, in fact, be able to change the value of the pointer to be the same as a .如果您在堆上分配数组并仅将指向它的指针存储在堆栈上,则可以为其分配一个值,在这种情况下,实际上您可以将指针的值更改为a .

From The C Programming Language :来自C 编程语言

The array name is the address of the zeroth element.数组名是第零个元素的地址。

There is one difference between an array name and a pointer that must be kept in mind.必须牢记数组名称和指针之间的一个区别。 A pointer is a variable.指针是一个变量。 But an array name is not a variable.但是数组名不是变量。

My understanding is that the array name is a constant, so it can't be assigned.我的理解是数组名是一个常量,所以不能赋值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM