如果我理解正确,您将使用指针从字符串文字"jklmno" 中输出字母“l”。
此文字位于索引为 1 的行中,以及索引为 1 的列中。
因此,要使用下标运算符访问文字,您可以编写表达式p[1][1],它产生指向字符串文字第一个字符的指针。现在要获取字符串文字的字符“l”,您可以编写表达式p[1][1][2]。
printf( "%c\n", p[1][1][2] );
现在让我们使用不带下标运算符的指针来做同样的事情。
表达式中使用的数组指示符(极少数例外)被转换为指向其第一个元素的指针。
因此在表达式中使用的数组指示符p 被转换为指向数组第一行的char * ( * )[2] 类型的指针。
要获得指向数组第二行的指针,您应该编写 p + 1。
要获取行本身,您必须取消引用指针
*( p + 1 )
这个表达式的类型是char *[2]。
但同样,由于该表达式是一维数组的指示符,然后在表达式中使用,它被转换为指向其第一个元素的指针,并具有 char ** 类型。
要访问指向行的第二个元素的指针,您可以使用指针算法
*( p + 1 ) + 1
要获取指向的元素(字符串文字),您必须取消引用指针
*( *( p + 1 ) + 1 )
此表达式的类型为 char *,并指向字符串文字 "jklmno" 的第一个字符。
要获得指向字符串文字第三个字符的指针,您必须使用此表达式
*( *( p + 1 ) + 1 ) + 2
现在您需要取消引用指针以输出指向的字母'l'。
*( *( *( p + 1 ) + 1 ) + 2 )
所以函数调用看起来像
printf( "%c\n", *( *( *( p + 1 ) + 1 ) + 2 ) );
将其与之前显示的函数调用进行比较
printf( "%c\n", p[1][1][2] );
考虑到如果你有一个类似的数组
T a[N];
其中T 是某种类型,然后使用下标运算符访问数组的i-th 元素,您可以编写表达式a[i]。在引擎盖下,这个表达式是使用像*( a + i ) 这样的指针算术计算的。由于加法运算符的交换性质,这个表达式也可以写成*( i + a )..所以使用下标运算符你可以写出表达式i[a],它等价于表达式a[i]。
来自 C 标准(6.5.2.1 数组下标)
2 后缀表达式后跟方括号 [] 中的表达式
是数组对象元素的下标名称。这
下标运算符 [] 的定义是 E1[E2] 等同于
(*((E1)+(E2)))。由于适用于
二进制 + 运算符,如果 E1 是一个数组对象(相当于一个指针
到数组对象的初始元素)并且 E2 是一个整数,
E1[E2] 表示 E1 的第 E2 个元素(从零开始计数)。
因此表达式
*( *( *( p + 1 ) + 1 ) + 2 )
可以像这样重写
*( 2 + *( 1 + *( 1 + p ) ) )
相应地喜欢
2[1[1[p]]]
以及函数printf的调用
printf( "%c\n", p[1][1][2] );
也可以像这样重写(尽管您不应该这样做使代码混淆)
printf( "%c\n", 2[1[1[p]]] );
这是一个演示程序。
#include <stdio.h>
int main()
{
char *p[3][2] =
{
{ "abc", "defg" },
{ "hi", "jklmno" },
{ "pqrstuvw", "xyz" }
};
printf( "%c\n", 2[1[1[p]]] );
}
它的输出是
l