19

我在这里问过一个关于结构的类似问题,但我试图弄清楚 C 如何处理诸如分配变量之类的事情,以及如果它们在功能上相同,为什么不允许将它们分配给彼此。

假设我有两个数组:

int x[10];  
int y[10];  

为什么 x = y 不能编译?如果它们都是那样的相同“签名”,那么您不应该来回分配它们吗?

我可以以允许我在 C 中这样做的方式声明这些吗?对我来说,你可以做到这一点是有道理的,但也许有办法做到这一点?结构的类型定义似乎是解决方案,数组声明和赋值是否相同?

感谢你们的帮助,我是 Stackoverflow 的新手,但到目前为止它对我来说是一个非常好的资源!

4

7 回答 7

28

简单地说,数组是不可赋值的。它们是“不可修改的左值”。这当然引出了一个问题:为什么?请参阅此问题以获取更多信息:

为什么 C++ 支持在结构中按成员分配数组,但通常不支持?

数组不是指针。 x这里确实指的是一个数组,尽管在许多情况下,这个“衰减”(隐式转换)为指向其第一个元素的指针。同样,y数组的名称也是如此,而不是指针。

您可以在结构中进行数组赋值:

struct data {
    int arr[10];
};

struct data x = {/* blah */};
struct data y;
y = x;

但是你不能直接用数组来做。使用memcpy.

于 2009-04-13T16:50:40.723 回答
4
int x [sz];
int *y = x;

这编译并将yx.

于 2012-08-23T17:23:28.897 回答
2

这里的一些消息说数组的名称会产生其第一个元素的地址。这并不总是正确的:

#include <stdio.h>

int
main(void)
{
  int array[10];

  /*
   * Print the size of the whole array then the size of a pointer to the
   * first element.
   */
  printf("%u %u\n", (unsigned int)sizeof array, (unsigned int)sizeof &array[0]);

  /*
   * You can take the address of array, which gives you a pointer to the whole
   * array. The difference between ``pointer to array'' and ``pointer to the
   * first element of the array'' matters when you're doing pointer arithmetic.
   */
  printf("%p %p\n", (void*)(&array + 1), (void*)(array + 1));

  return 0;
}

输出:

40 4
0xbfbf2ca4 0xbfbf2c80
于 2009-04-13T17:11:04.543 回答
1

为了分配数组,您必须分配数组内的值。

IE。x=y 等价于

for(int i = 0; i < 10 < ++i)
{
x[i] = y[i];
}
于 2009-04-13T16:50:57.133 回答
1

为了补充空白的答案,我设计了以下程序:

localhost:~ david$ cat test.c
#include <stdlib.h>
#include <stdio.h>
int main (int argc, char * argv [])
{
  struct data {
    int c [2];
  } x, y;
  x.c[0] = x.c[1] = 0;
  y.c[0] = y.c[1] = 1;
  printf("x.c %p %i %i\n", x.c, x.c[0], x.c[1]);
  printf("y.c %p %i %i\n", y.c, y.c[0], y.c[1]);
  x = y;
  printf("x.c %p %i %i\n", x.c, x.c[0], x.c[1]);
  printf("y.c %p %i %i\n", y.c, y.c[0], y.c[1]);

  return 0;
}

执行时,输出如下:

x.c 0x7fff5fbff870 0 0
y.c 0x7fff5fbff860 1 1
x.c 0x7fff5fbff870 1 1
y.c 0x7fff5fbff860 1 1

重点是说明结构值的复制是如何发生的。

于 2011-06-01T19:16:22.733 回答
0

当说“int x[10]”时,是说“为 10 个整数保留一些空间并传递给我一个指向该位置的指针”。因此,要使副本有意义,您需要对所指向的内存进行操作,而不是“内存位置的名称”。

因此,要在此处复制,您将使用 for 循环或 memcpy()。

于 2009-04-13T16:53:15.787 回答
0

我使用了 C 编译器,它可以很好地编译......并且在运行时代码会使 x 指向 y 的数组。

您会看到,在 C 中,数组的名称是指向数组开头的指针。事实上,数组和指针本质上是可以互换的。您可以获取任何指针并像数组一样对其进行索引。

早在 70 年代初开发 C 语言时,它就适用于抽象程度略高于汇编语言的相对较小的程序。在那种环境下,能够轻松地在数组索引和指针数学之间来回切换非常方便。另一方面,复制整个数据数组是一件非常昂贵的事情,而且几乎没有什么值得鼓励或从用户那里抽象出来的事情。

是的,在当今时代,将数组的名称作为“整个数组”的简写而不是“数组前面的指针”会更有意义。然而,C 并不是在现代设计的。如果您想要一种语言,请尝试 Ada。x := y 完全符合您的期望;它将一个数组的内容复制到另一个数组。

于 2009-04-13T18:14:16.450 回答