【问题标题】:C: if a[i] is equivalent to *(a+i). What is the equivalent of a[j][i]?C:如果 a[i] 等价于 *(a+i)。 a[j][i] 的等价物是什么?
【发布时间】:2014-09-19 06:18:07
【问题描述】:

我对 C 语言中的这个问题感到非常困惑。

如果a[i] 等价于*(a+i)a[j][i] 的等价物是什么?

我知道(a+i) 将数组的第一个元素的内存地址增加 i 的值,然后使用 * 运算符取消引用该地址以获得该值。但是,我对多维数组感到困惑。在内存中,这些值就像一维数组一样存储,但我不明白如何像一维数组示例中那样使用变量 i 或 j 来增加内存地址。

由于某种原因,在一维数组中打印*a 将打印数组的第一个元素,而在多维数组中*a 将打印一个随机数。为什么会这样?

非常感谢任何帮助。

【问题讨论】:

  • 这可能很快退化成一个关于指针、数组、指针算术、数组跨步的完整教程,我可以看到指针数组的简单切线。在a good C text 的业务端工作一段时间并查看questions like this one 会对您有很大帮助。

标签: c arrays pointers multidimensional-array memory-address


【解决方案1】:

如果 a[i] 等价于 *(a+i)。 a[j][i]的等价物是什么?

 a[j][i] 

类似于

 *(*(a+ j) + i)

现在如果你想知道它是怎么回事?

那就看看

你已经知道了

a[j]=*(a+j)            -------------------------> res 1

现在

a[j][i] = *(a[j]+i);   --------------------------> res2

之后替换res1 中的res2。于是就变成了

a[j][i] = *(*(a+ j) + i)   ----------------------> res3

【讨论】:

  • 谢谢!但是,我仍然不太了解它的概念。在括号内,您在将 int j 添加到它之前取消引用 *(a+i) ,然后再次取消引用它。如果结果取决于第 i 个索引 (a[i]) 处的值而不是地址本身,这将如何工作?
  • @Mishy 为您澄清请参阅链接stackoverflow.com/questions/6673719/…
  • 这个答案将与下面@newacct 的断言一起完成
【解决方案2】:

这个问题的字面答案很简单:a[i] 按照标准定义为始终与*(a+i) 相同,因此,a[j][i] 保证始终与*(*(a+j)+i) 相同。 然而,这本身并不能帮助我们理解正在发生的事情;它只是将一种复合表达式转换为另一种。

a[j][i](以及扩展名*(*(a+j)+i))根据a 的类型做非常不同的事情。这是因为,根据类型的不同,可能存在不明显的隐式数组到指针转换。

在 C 中,数组类型 T[x] 的值在许多上下文中被隐式转换为指针类型 T* 的右值,其中一些包括下标运算符的左侧,以及一个操作数。因此,如果您执行a[i]*(a+i),并且a 是数组类型的表达式,则在这两种情况下,它都会转换为指向其第一个元素的指针(如&a[0]),并且它是参与的指针操作。因此,您可以看到*(a+i) 的意义。

如果a 具有T[x][y] 类型,它将是一个“真正的”多维数组,它是一个C 数组,其元素本身就是C 数组(具有一定的编译时间常数大小)。在这种情况下,如果您考虑*(*(a+j)+i),发生的情况是 1) a 被转换为指向其第一个元素的指针(这是指向数组的指针,类型为 T(*)[y]),2) 该指针是递增和取消引用,产生一个数组类型的值(ajth 子数组),3) 那个 数组然后转换为指向其第一个元素的指针(@ 类型的指针987654342@),然后 4) 递增和取消引用。这最终产生了ajth 元素的ith 元素,也就是你通常认为的a[j][i]

但是,a 也可以具有类型,例如 T**。这通常用于实现“假”多维数组,它是一个指针数组,然后依次指向某个数组的第一个元素。这允许您拥有可以具有不同大小的“行”(因此多维数组不必是“矩形”),并且大小在编译时不固定。 “行”以及主指针数组不必连续存储。在这种情况下,如果您考虑*(*(a+j)+i),正在发生的事情是 1) a 递增和取消引用,产生指针类型的值(ajth 元素),2) 指针然后递增和取消引用。这最终产生了由主指针数组的jth 元素引用的数组的ith 元素。请注意,在这种情况下,没有隐式的数组到指针的转换。

【讨论】:

    【解决方案3】:

    一般数组遵循指针的概念。对于一维数组,一次解引用就足以获取值。但在多维数组中,要获取值,我们在二维数组中解引用两次,在 3D 数组中解引用 3 次。

    a[j][i]=*(*(a+j)+i)

    【讨论】:

      【解决方案4】:

      C 中的多维数组是连续的。以下:

      int a[4][5];

      由 4 个 int[5] 组成,在内存中彼此相邻。

      指针数组:

      int *a[4];

      是锯齿状的。每个指针都可以指向不同长度的单独数组(的第一个元素)。

      a[i][j] 等价于 ((a+i)+j)。请参阅 C11 标准,第 6.5.2.1 节:

      The definition of the subscript operator [] is that E1[E2] is identical to (*((E1)+(E2)))
      

      因此,a[i][j]等价于(*(a+i))[j],等价于((a+i)+j)。

      之所以存在这种等价性,是因为在大多数情况下,数组类型的表达式会衰减为指向其第一个元素的指针(C11 标准,6.3.2.1)。 a[i][j] 解释如下:

      a is an array of arrays, so it decays to a pointer to a[0], the first subarray.
      a+i is a pointer to the ith subarray of a.
      a[i] is equivalent to *(a+i), dereferencing a pointer to the ith subarray of a. Since this is an expression of array type, it decays to a pointer to a[i][0].
      a[i][j] is equivalent to *(*(a+i)+j), dereferencing a pointer to the jth element of the ith subarray of a.
      

      请注意,指向数组的指针不同于指向其第一个元素的指针。 a+i 是指向数组的指针;它不是数组类型的表达式,并且无论是指向指针的指针还是指向任何其他类型的指针,它都不会衰减。

      and for some reason printing *a in single dimensional array will print the first element of the array whereas *a in a multidimensional array will print a random number. Why is this so? 
      

      对于二维数组,您需要相应地取消引用它,

      printf("\nvalue : %d",**a);
      

      打印数组的第一个元素。

      【讨论】:

        猜你喜欢
        • 2015-08-26
        • 1970-01-01
        • 1970-01-01
        • 2020-05-10
        • 2017-09-10
        • 2021-04-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多