简体   繁体   English

C 中的二维数组和指针 - 如何访问元素?

[英]2D array and pointer in C - how to access elements?

I have an example involving a pointer to a 2D array.我有一个涉及指向二维数组的指针的示例。 Can someone help me understand what is going on in this example?有人可以帮助我理解这个例子中发生了什么吗?

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;
}

data is a 2 dimentional array, which has 4 rows and each row has 3 elements (ie 4 X 3). data是一个二维数组,有 4 行,每行有 3 个元素(即 4 X 3)。

Now, Ptr = *data;现在, Ptr = *data; means you are storing the starting address of 1st row to the pointer variable Ptr .意味着您将第一行的起始地址存储到指针变量Ptr This statement is equivalent to Ptr = *(data + 0) .此语句等效于Ptr = *(data + 0) Ptr = *(data + 1) - this means we are assigning 2nd row's starting address. Ptr = *(data + 1) - 这意味着我们正在分配第二行的起始地址。

Then *Ptr or *(Ptr + 0) will give you the value of the first element of the row to which is pointing.然后*Ptr*(Ptr + 0)将为您提供指向的行的第一个元素的值。 Similarly, *(Ptr + 1) will give you the value of the second element of the row.同样, *(Ptr + 1)将为您提供该行第二个元素的值。

The for loop in your program is used to identify which row has the maximum value of the sum of its elements (3 elements).程序中的for循环用于确定哪一行具有其元素总和(3 个元素)的最大值。 Once the control comes out of that for loop, Ptr will be pointing to the row which has the maximum sum of its elements and sum0 will have the value of the sum.一旦控件退出for循环, Ptr将指向其元素总和最大的行,而sum0将具有总和的值。

Consider an array int a[5];考虑一个数组int a[5]; , I hope you know that a[0] and 0[a] is the same. , 我希望你知道a[0]0[a]是一样的。 This is because a[0] means *(a+0) and 0[a] means *(0 + a) .这是因为a[0]表示*(a+0)0[a]表示*(0 + a) This same logic can be used in 2 dimensional array.同样的逻辑可以用在二维数组中。

data[i][j] is similar to *(*(data + i) + j) . data[i][j]类似于*(*(data + i) + j) We can write it as i[data][j] also.我们也可以把它写成i[data][j]

For more details please refer to the book "Understanding Pointers in C" by Yashavant Kanetkar.有关更多详细信息,请参阅 Yashavant Kanetkar 撰写的《Understanding Pointers in C》一书。

Ptr = *data; is short for *(data+0)+0 which is a pointer for first column element of the first row.*(data+0)+0的缩写,它是第一行第一列元素的指针。 the first 0 added with data is the row no., which is indirected and takes us to the first row.添加数据的第一个 0 是行号,它是间接的,将我们带到第一行。 * (data+0) is still a address and not a value it points to (for 2D array). * (data+0)仍然是地址而不是它指向的值(对于二维数组)。 So, Ptr now points to the address of first column in first row.因此,Ptr 现在指向第一行第一列的地址。 The second zero is the column no.. So, first row and first column's memory address is chosen.第二个零是列号。因此,选择第一行和第一列的内存地址。 Using indirection (*) again would only now give value that the address holds.再次使用间接寻址 (*) 现在只会给出地址所持有的值。 like * (*(data+0)+0) or **data .* (*(data+0)+0)**data

Generally, if p is pointer name,i row number and j column number,一般如果p是指针名,i行号j列号,

  1. (*(p+i)+j) would give a memory address of a element in 2D array. (*(p+i)+j)将给出二维数组中元素的内存地址。 i is row no.我是排号and j is col no., j 是 col 号,
  2. *(*(p+i)+j) would give the value of that element. *(*(p+i)+j)将给出该元素的值。
  3. *(p+i) would access the ith row *(p+i)将访问第 i 行
  4. to access columns, add column number to *(p+i) .要访问列,请将列号添加到*(p+i) You may have to declare the pointer as (*p)[columns] instead of just *p .您可能必须将指针声明为(*p)[columns]而不仅仅是*p Doing so, you are declaring pointer to an 2D array.这样做,就是在声明一个指向二维数组的指针。

Using pointer arithmetic is treating 2d array like 1D array.使用指针算法将二维数组视为一维数组。 Initialize pointer *Ptr to first element ( int *Ptr = *data ) and then add an no.将指针 *Ptr 初始化为第一个元素 ( int *Ptr = *data ),然后添加一个编号。 ( Ptr + n ) to access the columns. ( Ptr + n ) 访问列。 Adding a number higher than column number would simply continue counting the elements from first column of next row, if that exists.添加一个高于列号的数字将简单地继续计算下一行第一列的元素(如果存在)。

data is an array of 3-element arrays of integers. data是 3 元素整数数组的数组。 In contexts that expect a "pointer to foo", you can use an "array of foo" and it will behave like a pointer to its first element, so *data is a pointer to the first element of data , namely (so to speak) {23,55,50} .在期望“指向 foo 的指针”的上下文中,您可以使用“foo 数组”,它的行为类似于指向其第一个元素的指针,因此*data是指向data的第一个元素的指针,即(可以这么说) {23,55,50}

So, the answer to the first question in the comments: No, it isn't true that Ptr = 23 .因此,评论中第一个问题的答案:不, Ptr = 23是不正确的。 (It couldn't be; Ptr is an int * and 23 is an int .) (不可能; Ptr是一个int *而 23 是一个int 。)

You are correct that Ptr = *(data+i) makes Ptr point to the i th row of data .您是正确的, Ptr = *(data+i)使Ptr指向第idata More precisely, data is an array of 3-element arrays of int, which behaves like a pointer to 3-element arrays of int;更准确地说, data是 int 的 3 元素数组的数组,其行为类似于指向 int 的 3 元素数组的指针; adding i to it moves past i such arrays.i添加到它会移动过去i这样的数组。

The usual way to access other columns of the array is ordinary array indexing.访问数组其他列的常用方法是普通数组索引。 If you refer to data[i][j] , you're getting column j of row i .如果您参考data[i][j] ,您将获得第i行的第j列。 If you want to do it with explicit pointer arithmetic, then note that (eg) Ptr in the example code is of type "pointer to integer", so Ptr+1 (for instance) is element 1 of whatever row Ptr is pointing to.如果您想使用显式指针算法来实现,请注意示例代码中的(例如) Ptr是“指向整数的指针”类型,因此Ptr+1 (例如)是Ptr指向的任何行的元素 1。 (But, as a matter of style, you should generally not do explicit pointer arithmetic when you don't actually need to.) (但是,作为一种风格问题,当您实际上不需要时,您通常不应该进行显式指针运算。)

In your example the loop goes through all matrix rows to find the one whose sum of all elements holds the maximum value.在您的示例中,循环遍历所有矩阵行以找到其所有元素之和保持最大值的行。

At the beginning a pointer to the first row is assigned:在开始时,分配了指向第一行的指针:

Ptr = *data;

Which means that the following is true:这意味着以下内容为真:

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

Notice that Ptr is a pointer so it holds a memory address, hence Ptr is different than 23 (unless the memory address happens to be 23 , which is unlikely to happen).请注意, Ptr是一个指针,因此它包含一个内存地址,因此Ptr不同于23 (除非内存地址恰好是23 ,这不太可能发生)。

C allows multidimensional arrays, lays them out in memory as contiguous locations, and does more behind the scenes address arithmetic. C 允许多维数组,将它们作为连续位置布置在内存中,并在幕后执行更多地址运算。 Consider a 2-dimensional array.考虑一个二维数组。

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

The compiler treats a 2 dimensional array as an array of arrays.编译器将二维数组视为数组的数组。 where an array name is a pointer to the first element within the array.其中数组名称是指向数组中第一个元素的指针。 So, arr points to the first 3-element array, which is actually the first row (ie, row 0) of the two-dimensional array.所以,arr指向第一个3元数组,其实就是二维数组的第一行(即第0行)。 Similarly, (arr + 1) points to the second 3-element array (ie, row 1) and so on.同样,(arr + 1) 指向第二个 3 元素数组(即第 1 行),依此类推。 The value of this pointer, (arr + 1), refers to the entire row.该指针的值(arr + 1) 指的是整行。 Since row 1 is a one-dimensional array, (arr + 1) is actually a pointer to the first element in row 1. Now add 2 to this pointer.由于第 1 行是一个一维数组,(arr + 1) 实际上是指向第 1 行第一个元素的指针。现在将 2 添加到该指针。 Hence, ( (arr + 1) + 2) is a pointer to element 2 (ie, the third element) in row 1. The value of this pointer, ( (arr + 1) + 2), refers to the element in column 2 of row 1.因此,( (arr + 1) + 2) 是指向第 1 行中元素 2(即第三个元素)的指针。该指针的值( (arr + 1) + 2) 指的是列中的元素第 1 行的 2 个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM