C数组声明和赋值?

Posted

技术标签:

【中文标题】C数组声明和赋值?【英文标题】:C array declaration and assignment? 【发布时间】:2010-10-19 04:12:21 【问题描述】:

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

假设我有两个数组:

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

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

我可以以允许我在 C 中执行此操作的方式声明这些吗?对我来说,你能够做到这一点是有道理的,但也许有办法做到这一点?结构的 typedef 似乎是解决方案,数组声明和赋值是否相同?

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

【问题讨论】:

【参考方案1】:

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

Why does C++ support memberwise assignment of arrays within structs, but not generally?

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

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

struct data 
    int arr[10];
;

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

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

【讨论】:

该代码仍然没有完成他想要它做的事情,不是吗?也许我错了,但我的印象是他希望将 y 数组的内容复制到 x 中。 是的。幸运的是,许多其他回复表明 memcpy() 是正确的选择。我会添加它... “数组的名称实际上是该数组的第一个元素的地址。\您在此处提供的示例代码试图分配给不是左值的东西。”:对于为了子孙后代,我想我会注意到投票率最高的答案中的这两个句子都是错误的。首先,数组的名称绝对不是指针(例如想想 sizeof()),它在许多情况下只是简单地衰减为指针。其次,数组名一个左值,只是不是一个可修改的左值。 我在劫持这个答案。它获得最高票数并被接受,但包含不正确的信息,并且用户早已不复存在。希望这可以解决问题。【参考方案2】:
int x [sz];
int *y = x;

这样编译,y 将与x 相同。

【讨论】:

y 将是一个等同于 &x[0] 的指针,由于数组到指针的转换,但它不会“相同”,因为 x 是一个数组,而不是一个指针。【参考方案3】:

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

#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

【讨论】:

【参考方案4】:

为了分配数组,您必须在数组中分配值。

即。 x=y 等价于

for(int i = 0; i < 10 < ++i)

x[i] = y[i];

【讨论】:

这就是为什么我要提供等价物! 它给人的印象是 x=y 是一个有效的陈述 实际上在 OP 中已经提到 x=y 无法编译。 x=y 对数组来说不可能是这个问题的全部内容,Naveen。【参考方案5】:

为了补充 Blank 的回答,我设计了以下程序:

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

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

【讨论】:

【参考方案6】:

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

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

【讨论】:

【参考方案7】:

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

你看,在 C 中,数组的名称是一个指向数组开头的指针。事实上,数组和指针本质上是可以互换的。您可以使用 any 指针并像数组一样对其进行索引。

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

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

【讨论】:

友好的随机 ping。 :) 毫无疑问,您(现在)知道,数组的名称不是指针。

以上是关于C数组声明和赋值?的主要内容,如果未能解决你的问题,请参考以下文章

String数组的定义和赋值

c语言赋值是啥?

C#/.NET6期01C#基础_10_11_12数组声明引用类型如果没有赋值的话则默认值为null

C#/.NET6期01C#基础_10_11_12数组声明引用类型如果没有赋值的话则默认值为null

C#/.NET6期01C#基础_10_11_12数组声明引用类型如果没有赋值的话则默认值为null

数组解构赋值