【问题标题】:Specifying a particular position in a 2D array [duplicate]指定二维数组中的特定位置[重复]
【发布时间】:2013-09-22 09:51:27
【问题描述】:

在二维数组中指定位置的方法是什么。我不是指通过下标获取值,而是以类似于一维数组的方式,在给定指针的情况下,可以使用+ 运算符并转到该位置。

例如,如果我有一些大小为 4 的数组 A,我可以通过 A + 2 转到第三个元素。

如果我有一个 2D 数组,我该怎么做?

【问题讨论】:

  • 你可以这样做,但你为什么要这样做?
  • A + rownum * ROWSIZE + colnum
  • @bspikol:不,这是不正确的。这会给你一个距离数组很远的指针(取决于 rownum 和 ROWSIZE 的值),并且它将是错误的类型(它将是指向 T 数组的指针,而不是指向 T 的指针)

标签: c++ arrays


【解决方案1】:

其中A 是数组,R 是行,C 是列。

*(A + R) + C

给你A[R][C]的地址

【讨论】:

  • 这有时会起作用,具体取决于数组的分配方式。请参阅下面的答案。
  • @Michael:除非您有第二个帐户,否则您没有发布答案。
  • 抱歉,本杰明,键盘速度太慢了,现在可以了。
  • @Michael:你的回答没有错,但我认为它没有解决问题。我认为问题在于特定案例的正确语法,而不是最佳实践。
  • 好吧,你的答案(以及大卫的)在技术上是正确的。我只是不想通过建议如何去做来鼓励不良做法。如果有人问我“我应该如何蒙住眼睛驾驶变速杆”,我不会开始描述齿轮和离合器。
【解决方案2】:

是的,你是对的。您可以通过将行维度乘以列大小并添加列索引来访问元素。

假设你的整数数组是arr[NUMBER_OF_ROWS][NUMBER_OF_COLUMNS],那么你可以访问arr[ROW_INDEX][COLUMN_INDEX]元素:

int num = *((int *)arr + ROW_INDEX * NUMBER_OF_COLUMNS + COLUMN_INDEX);

【讨论】:

    【解决方案3】:

    这个问题不清楚,但这里有一些想法。

    语言中没有多维数组,只支持一维数组,有一些额外的保证。通常所说的二维数组是给定类型数组类型的对象的一维数组。额外的保证是连续性和对齐:数组中的每个元素与数组中的下一个元素是连续的,并且数组和第一个元素是对齐的。

    数组倾向于衰减指向第一个元素的指针,您可以使用指针算法移动到数组中的下一个元素,这就是语法A + 2的含义:&A[0] + 2 或一个指针,它是数组中第一个(第零个)元素加 2 的结果。但是 decay 只是顶层数组。

    前面的保证意味着您可以像使用指向第一个元素的指针一样使用数组,并且该元素与数组本身位于完全相同的位置。将此递归应用于嵌套数组,您可以得到以下结果:

    int array[10][10];
    // array is an array of 10 arrays of 10 int
    // array[0] is an array of 10 int, the first subarray
    // array[0][0] is an int, the first element of the subarray
    int *p = &array[0][0];
    int *q = p + 10;           // One beyond the first subarray: pointer to the first
                               // element of the second subarray.
    int *r = p + 10*row + col; // pointer to the col-th element inside the row-th subarray
                               // equivalent to &array[row][col]
    

    【讨论】:

    • 我对本杰明的回答的评论也适用于这里:只有当您确信数组的声明完全如此并且声明永远不会改变时,这才有效。
    • 虽然我不希望任何编译器在这种情况下做任何我们都期望的事情之外的任何事情,但在技术上不是未定义的行为对指针执行算术导致结果是否在起始指针所在的数组的边界之外?所以,例如parray[0] 内部开始,然后p + 10array[0] 外部产生一个指针。我以为那是UB?
    • @BenjaminLindley:不同意。虽然标准中没有直接引用声称这是有效的,但这种行为是有保证的并且定义明确的。该标准规定了两个数组的布局,并且布局约束意味着第一个子数组的最后一个元素与第二个子数组的第一个元素是连续的,这意味着给定一个指向第一个元素的指针,您可以通过递增到达第二个元素指针加 1。
    【解决方案4】:

    通过一次取消引用一个级别。对于 2D 数组和 3D 数组:

    #include <cstdio>
    
    int A[2][2];
    
    int B[2][2][2];
    
    int main() {
        // Set A[1][1] to 2
        *(*(A+1) + 1) = 2;
        printf("%d\n", A[1][1]);
    
        // Set B[1][1][1] to 3
        *(*(*(B+1) + 1) + 1) = 3;
        printf("%d", B[1][1][1]);
    }
    

    一般而言,*(...*(*(array_of_N_dimensions + D1) + D2) ... + DN) 将为您提供对array_of_N_dimensions[D1][D2]...[DN] 的访问权限。

    【讨论】:

      【解决方案5】:

      基于指针算法的其他答案在技术上是正确的,但前提是您确定您的数组是像 A[rows][cols] 那样分配的。通常情况并非如此,即使您这样实现数组,您也不能确定其他开发人员不会重构它。当其他开发人员将类型 A[rows][cols] 更改为 vector> A 时,您的代码将中断。

      因此,我建议不要跨行使用指针算术。如果您担心性能 - 不要:编译器将自动使用指针算法来访问适用的数组元素。更重要的是,编译器不会在不适用的地方使用指针算法。

      【讨论】:

      • 向量不是数组,vector&lt;vector&lt;T&gt;&gt; 的内存布局与数组数组完全不同。多维矩阵的常见实现通常是单个vector&lt;&gt;rows*cols 元素和管理对象的类中的指针算法。我不认为我会使用vector&lt;vector&lt;T&gt;&gt; 来代替多个暗淡的数组(vector&lt;vector&lt;T&gt;&gt; 的唯一优点是它可以是锯齿状的,但数组不是这样!
      • 嗯,这只是一个会破坏指针算术代码的重构示例。而不是 vector > A 它应该是 non_continuous_container A。:)
      【解决方案6】:

      这里有一些自学测试代码。希望对您有所帮助。

      #include < iostream >
      
      int main()
      {
          int a[2][2];
      
          a[0][0] = 1;
          a[0][1] = 2;
          a[1][0] = 3;
          a[1][1] = 4;
      
      
          for (int i=0; i < 4; ++i)
          {
              std::cout << *(*a+i) << std::endl;
          }
      
          return 0;
      }
      

      【讨论】:

        【解决方案7】:

        二维数组在内存中逐行存储,因此您可以使用 index A+i*N+j 访问A[i][j],其中 N 是行长度。

        【讨论】:

        • 不,您绝对不能使用该表达式访问A[i][j]
        • 直到我发表评论后才注意到错字。它仍然是错误的。在原始问题下方查看我对 bspikol 的评论。
        • 除了打字我看不出为什么这是一个错误的索引,你能澄清一下吗?
        • 希望这清楚地说明了问题:ideone.com/72oWzE
        • 我不知道您所说的“索引正确”是什么意思。如果您的意思是“指针指向正确的位置”,那么不是。
        猜你喜欢
        • 2014-09-07
        • 1970-01-01
        • 2017-05-18
        • 1970-01-01
        • 1970-01-01
        • 2017-04-11
        • 2010-12-08
        • 2015-11-04
        相关资源
        最近更新 更多