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

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

假设我有两个数组:

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

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

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

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

【问题讨论】:

    标签: c arrays variable-assignment


    【解决方案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。 :) 毫无疑问,您(现在)知道,数组的名称不是指针。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2010-12-10
          • 2010-12-07
          • 2021-01-01
          • 2014-09-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多