"C" 试图理解 **pointer 以及如何访问 value[][] 的所有值
"C" Trying to understand **pointer and how to access all values of value[][]
#include "stdio.h"
int main()
{
int *pI, *values[2];
int i1[] = {1, 2}, i2[][2] = {{5, 10}, {20, 30}};
// SOME LINES ARE EDITED, AFTER READING COMMENTS
*values = i2[*i1]; // i2[1] = 20 // values[0] = &i2[1][0];
values[1] = i1; // values[1] = 1
pI = &i2[0][0]; //pI = 5
printf(" %d %d\n", **values, *&values[1][1]); //...
// (Edited) expectation: **values = 20 *&values[1][1] = 2
// Result: **values = 20 *&values[1][1] = 2
*pI += pI[i1[1]]; // pI[0] += pI[2] = 5 + 20 = 25
*values = pI; // values points to the 25 (pI)
*(i1 + 1) *= *(values[1] + 1); // i1[1]=2 // i1[1] *= i1[1] = 2*2
printf(" %d %d\n", **values, *&values[1][1]);
// (Edited) expectation: **values = 25 *&values = 4
// Result: **values = 25 *&values = 4
return 0;
}
如你所见,我对这段代码的理解并不是蛋黄。
但是我想了解一下步骤,下次自己解决
由于下标运算符的定义,表达式*values
与values[0]
相同。
因此这个声明
*values = i2[*i1];
可以改写成下面的方式
values[0] = i2[i1[0]];
当 i1[0] 产生值 1 时
values[0] = i2[1];
表达式 i2[1] 生成数组 i2 的第二个元素,即 int[2]
类型的 one-dimensional 数组,值为 {20, 30}
.
在极少数情况下,表达式中使用的数组指示符被转换为指向其第一个元素的指针。所以你可以写
values[0] = &i2[1][0];
因此表达式 **values
的值等于 20。
再次声明
values[1] = i1;
数组指示符 i1 被转换为指向其第一个元素的指针。那就是你可以写
values[1] = &i1[0];
在这个表达式中 *&values[1][1]
这对运算符 *& 事实上没有任何作用。你可以写values[1][1]
。所以这个表达式产生数组 i1
的第二个元素,它等于 2
.
变量pI
pI = &i2[0][0];
指向元素&i2[0][0]
。这条记录可能被解读为
pI = ( int * )i2;
这条语句
*pI += pI[i1[1]];
可以改写成
*pI += pI[2];
pI[2]的值为20(数组i2
类型int
的第三个元素。
你有SP
*pI += 20;
因此元素 i2[0][0]
将包含 25
.
这条语句
*values = pI;
等同于
values[0] = pI;
所以现在指针 values[0]
指向元素 i2[0][0]
,即指向使用表达式 **values
.
输出的值 25
这个表达式语句
*(i1 + 1) *= *(values[1] + 1);
可以改写成
i1[1] *= *( values[1] + 1 );
由于上面的陈述
values[1] = i1;
values[1]
指向数组的第一个元素i1
。所以表达式 values[1] + 1
指向数组 i1
的第二个元素,它等于 2
.
所以你有
i1[1] *= 2;
因此 i1[1]
等于 4
。
这个值由表达式 *&values[1][1]
输出,正如上面提到的,它等同于 values[1][1]
要理解指针算法和数组指示符到指向其第一个元素的指针的隐式转换,不需要编写这样的混淆代码。
#include "stdio.h"
int main()
{
int *pI, *values[2];
int i1[] = {1, 2}, i2[][2] = {{5, 10}, {20, 30}};
// SOME LINES ARE EDITED, AFTER READING COMMENTS
*values = i2[*i1]; // i2[1] = 20 // values[0] = &i2[1][0];
values[1] = i1; // values[1] = 1
pI = &i2[0][0]; //pI = 5
printf(" %d %d\n", **values, *&values[1][1]); //...
// (Edited) expectation: **values = 20 *&values[1][1] = 2
// Result: **values = 20 *&values[1][1] = 2
*pI += pI[i1[1]]; // pI[0] += pI[2] = 5 + 20 = 25
*values = pI; // values points to the 25 (pI)
*(i1 + 1) *= *(values[1] + 1); // i1[1]=2 // i1[1] *= i1[1] = 2*2
printf(" %d %d\n", **values, *&values[1][1]);
// (Edited) expectation: **values = 25 *&values = 4
// Result: **values = 25 *&values = 4
return 0;
}
如你所见,我对这段代码的理解并不是蛋黄。 但是我想了解一下步骤,下次自己解决
由于下标运算符的定义,表达式*values
与values[0]
相同。
因此这个声明
*values = i2[*i1];
可以改写成下面的方式
values[0] = i2[i1[0]];
当 i1[0] 产生值 1 时
values[0] = i2[1];
表达式 i2[1] 生成数组 i2 的第二个元素,即 int[2]
类型的 one-dimensional 数组,值为 {20, 30}
.
在极少数情况下,表达式中使用的数组指示符被转换为指向其第一个元素的指针。所以你可以写
values[0] = &i2[1][0];
因此表达式 **values
的值等于 20。
再次声明
values[1] = i1;
数组指示符 i1 被转换为指向其第一个元素的指针。那就是你可以写
values[1] = &i1[0];
在这个表达式中 *&values[1][1]
这对运算符 *& 事实上没有任何作用。你可以写values[1][1]
。所以这个表达式产生数组 i1
的第二个元素,它等于 2
.
变量pI
pI = &i2[0][0];
指向元素&i2[0][0]
。这条记录可能被解读为
pI = ( int * )i2;
这条语句
*pI += pI[i1[1]];
可以改写成
*pI += pI[2];
pI[2]的值为20(数组i2
类型int
的第三个元素。
你有SP
*pI += 20;
因此元素 i2[0][0]
将包含 25
.
这条语句
*values = pI;
等同于
values[0] = pI;
所以现在指针 values[0]
指向元素 i2[0][0]
,即指向使用表达式 **values
.
25
这个表达式语句
*(i1 + 1) *= *(values[1] + 1);
可以改写成
i1[1] *= *( values[1] + 1 );
由于上面的陈述
values[1] = i1;
values[1]
指向数组的第一个元素i1
。所以表达式 values[1] + 1
指向数组 i1
的第二个元素,它等于 2
.
所以你有
i1[1] *= 2;
因此 i1[1]
等于 4
。
这个值由表达式 *&values[1][1]
输出,正如上面提到的,它等同于 values[1][1]
要理解指针算法和数组指示符到指向其第一个元素的指针的隐式转换,不需要编写这样的混淆代码。