让我们从引用C标准中有关数组和隐式转换(6.3.2.1 L值、数组和函数指示符)的有用引语开始.
3除非它是sizeof运算符的操作数,或者是一元&;
运算符,或者是用于初始化数组的字符串文字,an
expression that has type "array of type" is converted to an expression
with type "pointer to type" that points to the initial element of the
array object,而不是左值.如果数组对象已注册
存储类,则行为未定义.
举个例子,如果你有一个这样的数组
int a[num1][num2];
然后在引号中提到的极少数例外的表达式中使用,它被隐式转换为指向其初始元素的指针.
二维数组a
的元素又是类型int[num2]
的array.指向数组的元素类型的指针具有类型int ( * )[num2]
.您可以通过以下方式声明相应的指针
int ( *p )[num2] = a;
这是相同的
int ( *p )[num2] = &a[0];
现在,指针p
指向二维数组a
的第一行.在使用前缀增量运算符++p
或后缀增量运算符p++
递增它之后,它将指向数组a
的类型int[num2]
的下一个(第二)元素(行).取消对指针的引用,如*p
,您将获得指针指向的int[num2]
类型的一维数组(ROW).要将下标运算符( *p )[i]
应用于结果表达式,您将获得数组a
的当前行的i-th
元素.
另一方面,如果你有
int ( *p )[num2] = a;
则表达式p + num1
将指向数组a
的最后一个元素(类型为int[num2]
的一维数组)之后的存储器.表达式p + num1
等同于表达式a + num1
(由于将数组a
隐式转换为指向其初始元素的指针),该表达式a + num1
又等同于表达式&a[num1]
.根据最后一个表达式,用C标准编写(6.5.3.2地址和间接运算符)
3一元&;运算符得出其操作数的地址.如果
操作数的类型为"type",结果的类型为"指向类型的指针".如果
操作数是一元*运算符的结果,既不是该运算符也不是
对&;运算符进行求值,结果就好像两者都被省略了,
只是运算符上的约束仍然适用,并且
结果不是左值.如果不是Similarly, if the operand is the result of
a [] operator, neither the & operator nor the unary * that is implied
by the [] is evaluated and the result is as if the & operator were
removed and the [] operator were changed to a+ operator.,
结果是一个指针,指向由其
运算数.
因此,从引号中可以看出,表达式&a[num1]
等同于表达式a + num1
.
因此,这是for循环
for ( p = &a[0]; p < &a[num1]; p++ )
( *p )[i] = 0;
可以重写为
for ( p = a; p < a + num1; p++ )
( *p )[i] = 0;
至于下标运算符则(C标准,6.5.2.1数组下标):
2后缀表达式后跟方括号中的表达式[]
是数组对象的元素的下标指定.这个
下标运算符[]的定义是:E1[E2]相同
至(*((E1)+(E2).由于适用于
二进制+运算符,如果e1是数组对象(等效于指向
数组对象的初始元素),并且E2是整数,e1[e2]
指定E1的第2个元素(从零开始计数).
因此,For循环体中的以下表达式语句
( *p )[i] = 0;
也可以重写为
*( *( p + 0 ) + i ) = 0;
或者喜欢
*( *p + i ) = 0;