C中的二维数组和指针 – 如何访问元素?
我有一个涉及指向2D数组的指针的示例。 有人可以帮我理解这个例子中发生了什么吗?
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 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
是一个2维数组,有4行,每行有3个元素(即4 X 3)。
现在, Ptr = *data;
表示您将第1行的起始地址存储到指针变量Ptr
。 该语句相当于Ptr = *(data + 0)
。 Ptr = *(data + 1)
– 这意味着我们正在分配第二行的起始地址。
然后*Ptr
或*(Ptr + 0)
将给出指向的行的第一个元素的值。 类似地, *(Ptr + 1)
将为您提供行的第二个元素的值。
程序中的for
循环用于标识哪一行具有其元素总和的最大值(3个元素)。 一旦控件从for
循环中出来, Ptr
将指向具有其元素的最大总和的行, sum0
将具有该总和的值。
考虑一个数组int a[5];
,我希望你知道a[0]
和0[a]
是一样的。 这是因为a[0]
表示*(a+0)
, 0[a]
表示*(0 + a)
。 这种相同的逻辑可用于二维arrays。
data[i][j]
类似于*(*(data + i) + j)
。 我们也可以把它写成i[data][j]
。
有关详细信息,请参阅yashwant kanetkar中的“了解c中的指针”一书。
Ptr = *data;
是*(data+0)+0
缩写,它是第一行第一列元素的指针。 添加数据的第一个0是行号,它是间接的并将我们带到第一行。 * (data+0)
仍然是一个地址,而不是它指向的值(对于2D数组)。 所以,Ptr现在指向第一行第一列的地址。 第二个零是列号。因此,选择第一行和第一列的存储器地址。 再次使用间接(*)只会给出地址所拥有的值。 喜欢* (*(data+0)+0)
或**data
。
通常,如果p是指针名称,i行号和j列号,
-
(*(p+i)+j)
将给出2D数组中元素的存储器地址。 我排第一。 和j是col no。, -
*(*(p+i)+j)
将给出该元素的值。 -
*(p+i)
将访问第i行 - 要访问列,请将列号添加到
*(p+i)
。 您可能必须将指针声明为(*p)[columns]
而不是*p
。 这样做,您将声明指向2D数组的指针。
使用指针运算是像二维数组一样处理二维数组。 将指针* Ptr初始化为第一个元素( int *Ptr = *data
),然后添加一个no。 ( Ptr + n
)访问列。 添加高于列号的数字只会继续计算下一行第一列中的元素(如果存在)。
data
是一个3元素整数数组的数组。 在期望“指向foo的指针”的上下文中,你可以使用“foo数组”,它的行为就像指向第一个元素的指针,所以*data
是指向*data
的第一个元素的指针,即(可以这么说) ) {23,55,50}
。
所以,评论中第一个问题的答案是:不, Ptr = 23
并不是真的。 (它不可能; Ptr
是一个int *
,23是一个int
。)
你是正确的, Ptr = *(data+i)
使得Ptr
指向第i
行data
。 更准确地说, data
是一个由3个元素组成的int数组,其行为类似于指向int的3元素数组的指针; 添加i
到它移动过i
这样的数组。
访问数组其他列的常用方法是普通数组索引。 如果您参考data[i][j]
,那么您将获得第i
行的i
j
列。 如果你想用显式指针算术做,那么请注意(例如)示例代码中的Ptr
是“指向整数的指针”类型,因此Ptr+1
(例如)是Ptr
指向的任何行的元素1。 (但是,作为一种风格问题,当你实际上不需要时,通常不应该进行显式指针算法。)
在您的示例中,循环遍历所有矩阵行以查找其所有元素的总和保持最大值的行。
在开始时,指定指向第一行的指针:
Ptr = *data;
这意味着以下情况属实:
(Ptr[0] == 23 && Ptr[1] == 55 && Ptr[2] == 50)
请注意, Ptr是一个指针,因此它保存一个内存地址,因此Ptr不同于23 (除非内存地址恰好是23 ,这不太可能发生)。