10

我有一个涉及指向二维数组的指针的示例。有人可以帮我理解这个例子中发生了什么吗?

int main()
{

    int i = 0, j=0, sum0=0, sum1=0;
    int data[4][3] = { {23,55,50},{45,38,55},{70,43,45},{34,46,60}};
    int *Ptr;
    Ptr = *data;    //Why is the indirection operator used here? 
                    // Does Ptr = 23 by this assignment?

    for (i=0; i<4; i++) {
        sum1 = 0;
        for (j = 0; j < 3; j++) {
            sum1 += data[i][j];
        }
        if (sum1 > sum0) {
                 sum0 = sum1;
                 Ptr = *(data + i);     // Seems like this statement makes Ptr
        }                               // point one row below ... what syntax
    }                                   // can you use to access columns then?
                                       // Is it possible to use pointer arithmetic
    for (i=0; i<3; i++)                 // to access elements of data[i][j] that
        printf("%d\n", Ptr[i]);          // are not at j = 0?

  return 0;
}
4

5 回答 5

21

data是一个二维数组,它有 4 行,每行有 3 个元素(即 4 X 3)。

现在,Ptr = *data;意味着您将第一行的起始地址存储到指针变量Ptr中。该语句等价于Ptr = *(data + 0)Ptr = *(data + 1)- 这意味着我们正在分配第二行的起始地址。

然后*Ptror*(Ptr + 0)会给你指向的行的第一个元素的值。同样,*(Ptr + 1)将为您提供该行的第二个元素的值。

程序中的for循环用于确定哪一行具有其元素之和(3 个元素)的最大值。一旦控件退出该for循环,Ptr它将指向具有最大元素总和的行,并将具有总和sum0的值。

考虑一个数组int a[5];,我希望你知道a[0]并且0[a]是一样的。这是因为a[0]手段*(a+0)0[a]手段*(0 + a)。同样的逻辑可以用于二维数组。

data[i][j]类似于*(*(data + i) + j)。我们也可以这样写i[data][j]

有关详细信息,请参阅 Yashavant Kanetkar 的《理解 C 中的指针》一书。

于 2012-06-24T13:29:03.000 回答
7

Ptr = *data;*(data+0)+0是第一行的第一列元素的指针的缩写。添加数据的第一个 0 是行号,它是间接的并将我们带到第一行。* (data+0)仍然是一个地址,而不是它指向的值(对于二维数组)。所以,Ptr 现在指向第一行第一列的地址。第二个零是列号。因此,选择了第一行和第一列的内存地址。现在再次使用间接 (*) 只会给出地址持有的值。喜欢* (*(data+0)+0)**data

一般来说,如果 p 是指针名,i 行号和 j 列号,

  1. (*(p+i)+j)将给出二维数组中元素的内存地址。我是行号。j是列号,
  2. *(*(p+i)+j)将给出该元素的值。
  3. *(p+i)将访问第 i 行
  4. 要访问列,请将列号添加到*(p+i). 您可能必须将指针声明为(*p)[columns]而不仅仅是*p. 这样做,您将声明指向 2D 数组的指针。

使用指针算法将二维数组视为一维数组。将指针 *Ptr 初始化为第一个元素 ( int *Ptr = *data),然后添加一个 no。( Ptr + n) 访问列。添加一个大于列号的数字只会继续计算下一行第一列的元素(如果存在)。

于 2015-06-11T12:33:21.207 回答
1

data是一个由 3 元素整数数组组成的数组。在期望“指向 foo 的指针”的上下文中,您可以使用“foo 数组”,它的行为类似于指向其第一个元素*data的指针,指向 的第一个元素的指针也是data如此,即(可以这么说){23,55,50}

所以,评论中第一个问题的答案:不,这不是真的Ptr = 23。(不可能;Ptr是一个int *,而 23 是一个int。)

你是正确的,Ptr = *(data+i)指出Ptrith 行data。更准确地说,data是一个由 int 的 3 元素数组组成的数组,其行为类似于指向 int 的 3 元素数组的指针;添加i到它会经过i这样的数组。

访问数组其他列的常用方法是普通数组索引。如果您参考data[i][j],您将获得 column jof row i。如果您想使用显式指针算术来执行此操作,请注意Ptr示例代码中的(例如)是“指向整数的指针”类型,因此Ptr+1(例如)Ptr是指向任何行的元素 1。(但是,就风格而言,当您实际上不需要时,通常不应该进行显式指针运算。)

于 2012-06-24T12:35:04.897 回答
0

在您的示例中,循环遍历所有矩阵行以找到所有元素之和保持最大值的行。

在开始时,分配了指向第一行的指针:

Ptr = *data;

这意味着以下情况属实:

(Ptr[0] == 23 && Ptr[1] == 55 && Ptr[2] == 50)

请注意,Ptr是一个指针,因此它包含一个内存地址,因此Ptr不同于23(除非内存地址恰好是23,这不太可能发生)。

于 2012-06-24T12:41:16.703 回答
0

C 允许多维数组,将它们作为连续的位置放置在内存中,并在幕后进行更多的地址运算。考虑一个二维数组。

int arr[ 3 ][ 3 ] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};

编译器将二维数组视为数组数组。其中数组名是指向数组中第一个元素的指针。因此,arr 指向第一个 3 元素数组,它实际上是二维数组的第一行(即第 0 行)。类似地,(arr + 1) 指向第二个 3 元素数组(即第 1 行),依此类推。此指针的值(arr + 1) 指的是整行。由于第 1 行是一维数组,因此 (arr + 1) 实际上是指向第 1 行第一个元素的指针。现在将此指针加 2。因此, ( (arr + 1) + 2) 是指向第 1 行中元素 2(即第三个元素)的指针。该指针的值( (arr + 1) + 2) 指向列中的元素第 1 行的 2。

于 2020-08-28T08:00:27.790 回答