[英]2-D Arrays and pointers
有人告诉我编译器在必要时将数组名称转换为指向数组第1个元素的指针。 所以我用这个规则解决了很多问题,直到我看到这一切都很好。
int main()
{
int a[2][3] = {{1,2,3}, {5,6,7}}, (*p)[3];
p = a[0];
for(int i = 0; i < 3; i++)
printf("%d", (*p)[i]);
}
带代码块的输出为123
。
我试图解决它:
(*p)[i])
应该与*((*p)+i)
....(1)相同
如规则所说, “数组名将转换为指向数组第1个元素的指针”。 我将第二条指令p=a[0]
为p=&a[0][0]
(因为a[0]
是其第一元素为a[0][0]
的子数组名称)。 因此(*p)
可以写成(*(&a[0][0]))
。 与a[0][0]
。 因此eqn(1)变为
*(a[0][0]+i).
这就是我被困住的地方。 a[0][0]+i
是一个元素,而不是地址。 因此,对它应用*
运算符是无效的。 但是我也替换了语句p=a[0];
与p=&a[0][0];
在原始代码中,答案保持不变。 我也用p=&a[0];
代替了它p=&a[0];
。 答案仍然保持不变。 现在我超级困惑。
2D数组是1D数组的数组
在一维阵列中
a[0] => *(a) -> first element of array
a[1] => *(a + 1) -> second element of array
在二维数组中
a => the adress of first array
a[0] => *(a) -> the first array
a[0][0] => *(*(a)) -> the first element of first array
a[0][1] => *(*(a) + 1) -> second element of first array
a[1][1] => *(*(a + 1) + 1) -> second element of second array
这行是不正确的:
p = a[0];
p
的类型是3 int
数组的指针。 a[0]
的类型是int
指针。 您的编译器应该为此警告您。 如果没有,请启用任何必需的开关以打开大多数或所有编译器警告。 编译器发出警告时,请不要忽略它-在继续之前,请确保您理解了为什么编译器发出警告。 启用将警告转换为错误的编译器功能将是一个好主意。
正确的陈述是p = a;
或p = &a[0];
。 但是,让我们检查一下程序中发生了什么。 在表达式a[0]
:
a[0]
等效于*(a+0)
(从技术上来说是(*((a)+(0)))
,但在这种情况下我们不需要多余的括号)。 a
是一个数组,因此将其转换为指向其第一个元素的指针。 因此a
被转换为指向a[0]
的指针。 因此,表达式现在为*(&a[0] + 0)
。 0
加到&a[0]
不会更改它,因此结果是&a[0]
,表达式现在是*&a[0]
。 *
应用于指针会产生所指向的内容,因此表达式变为a[0]
。 a[0]
是3 int
的数组。 由于它是一个数组,因此将其转换为指向其第一个元素的指针。 因此结果实际上是&a[0][0]
。 观察到&a[0][0]
是一个指向int
的指针,如我上面所写。 所以现在我们看到p = a[0];
右侧有一个指向int
的指针,而左侧有一个指向3 int
数组的指针。 这违反了C标准中的约束,并且编译器必须为其发出诊断消息。
警告之后,编译器可能所做的就是转换指针,导致p
设置为指向a[0]
。
我将第二条指令
p=a[0]
为p=&a[0][0]
( 因为a[0]
是其第一元素为a[0][0]
的子数组名称 )。 因此(*p)
可以写成(*(&a[0][0]))
。
这是个错误。 尽管您执行了赋值p = a[0]
,但这并未将&a[0][0]
赋给p
,并且p
行为并不像是&a[0][0]
。 赋值将 &a[0][0]
转换为p
的类型。 p
保持声明的类型,它是一个指向3 int
数组的指针。 实际上, p
以&a[0]
的值结束。
现在我们可以评估(*p)[i]
:
p
是&a[0]
,因此表达式变为(*&a[0])[i])
。 *&a[0]
为a[0]
,因此表达式变为a[0][i]
。 i
的元素0的a
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.