【问题标题】:About array pointer关于数组指针
【发布时间】:2021-01-11 13:37:49
【问题描述】:

如何从这个数组指针中获取 'l'?

char *p[3][2] = {"abc", "defg", "hi", "jklmno", "pqrstuvw", "xyz"};

喜欢

printf("%c\n",*((*p)) + 2);

【问题讨论】:

  • 显示你要输出的内容。
  • 使用下标,而不是* 的间接引用。发明下标是有原因的。它们更容易阅读和正确。你需要p[1][1][2]p 获取l。如果你很反常,想要用间接方式做到这一点,请反复使用p[i] === *(p + i)。嵌套会很乱。

标签: arrays c pointers implicit-conversion string-literals


【解决方案1】:

让我们使用完全用大括号括起来的声明来使您的数组初始值设定项更清晰

char *p[3][2] = {{"abc", "defg"}, {"hi", "jklmno"}, {"pqrstuvw", "xyz"}};

现在您可以看到 p[1] 是数组 {"hi", "jklmno"}
那么你想得到第二个字符串,即p[1][1],然后是第三个字符:p[1][1][2]

这是一个运行示例:https://ideone.com/Jd9GWI

【讨论】:

  • 原文是对的但不是特别好的风格。标准是这样说的(主要是出于向后兼容性的原因,但这并没有降低它的正确性)。它没有被标准的“未来方向”部分标记为弃用。使用“让我们更正你的路线”是夸大其词;使用“让我们{clarify|revise}你的行”不会夸大其词。使用“让我们使用完全用大括号括起来的声明来使你的数组​​初始化器更清晰”会很好,如果在“大括号封闭”上有点笨拙的话;我可能会使用“全括号”,但标准所说的是“括号括起来”。
【解决方案2】:

如果我理解正确,您将使用指针从字符串文字"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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多