鱼C论坛

 找回密码
 立即注册
查看: 1018|回复: 7

*(*(*p)[i]+j)和*((*p)[i]+j)

[复制链接]
发表于 2023-7-29 09:46:14 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
#include <stdio.h>

int main()
{
        char *array[5] = {"FishC","Five","Star","Good","WoW"};
        char *((*p))[5] = &array;
        int i,j;
       
        for(i = 0;i < 5;i++)
        {
                for(j = 0; *(*(*p)[i]+j) != '\0';j++)
                {
                        printf("%c ",*(*(*p)[i]+j));
                }
                printf("\n");
        }
        return 0;
}
敢问各位带佬,上述代码为何无法实现字符串字符逐个输出呢?*(*(*p)[i]+j)代表的是什么意思呢?为什么将其替换为*((*p)[i]+j)就可实现了呢?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-7-29 09:46:34 | 显示全部楼层
上述代码无法实现字符串字符逐个输出的原因是指针的解引用方式不正确。让我们一步一步解析它。

首先,让我们看看*(*(*p)[ i]+j)代表什么意思。在给定的代码中,p是一个指向指针数组的指针,即char *((*p))[5]。这意味着p指向一个包含5个指针的数组,每个指针都指向char类型的数据。

现在,将其分解为更可读的形式:
· (*p)[ i]:首先,(*p)将取出指针数组的值,即array。然后,[ i]表示取出数组中的第i个元素,这里对应着指向字符串的指针。
· *((*p)[ i]+j):接下来,我们再次使用*进行解引用操作。(*p)[ i]表示获取到的字符串指针,然后加上j进行偏移,最后再次使用*解引用得到字符。

换句话说,*(*(*p)[ i]+j)的目的是获取二维字符数组中特定位置的字符。

然而,在该代码中,此解引用方式不正确。正确定义的指针解引用方式应该是*((*p)[ i]+j)。修正后的代码如下:
#include <stdio.h>
int main() {
    char *array[5] = {"FishC", "Five", "Star", "Good", "WoW"};
    char *(*p)[5] = &array;
    int i, j;
    
    for (i = 0; i < 5; i++) {
        for (j = 0; (*(*p)[ i] + j) != '\0'; j++) {
            printf("%c ", *(*(*p)[ i] + j));
        }
        printf("\n");
    }
    
    return 0;
}

通过这种修正,代码将能够实现逐个输出字符串的字符。
如果问题已经解决,请设置最佳答案
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-29 09:46:44 | 显示全部楼层
首先,我们来解释一下  *(*(*p)[ i]+j)  和  *((*p)[ i]+j)  这两个表达式的含义:

1.  *(*(*p)[ i]+j) :
   ·  *p : 这是一个指向指针的指针,指向的是数组  char *array[5] 。
   ·  (*p)[ i] : 这是一个指向 char 类型的指针,指向  array[ i]  这个字符串的首字符。
   ·  *((*p)[ i]+j) : 这是一个 char 类型的值,表示  array[ i]  字符串中的第  j  个字符。

2.  *((*p)[ i]+j) :
   ·  *p : 这是一个指向指针的指针,指向的是数组  char *array[5] 。
   ·  (*p)[ i] : 这是一个指向 char 类型的指针,指向  array[ i]  这个字符串的首字符。
   ·  *((*p)[ i]+j) : 这是一个 char 类型的值,表示  array[ i]  字符串中的第  j  个字符,和前面的表达式一样。

现在我们来看一下为什么  *(*(*p)[ i]+j)  无法实现字符串字符逐个输出,而将其替换为  *((*p)[ i]+j)  可以实现:

原因在于对于这个特定的代码片段,我们在声明指针  char *((*p))[5] = &array;  时, p  被声明为一个指向指针的指针,即  **p 。这是因为  *p  与  array  的类型一致,都是指向  char  类型的指针,而数组名  array  在这里退化成了指向首元素的指针。

因此,我们应该使用  **p  来表示  array  数组。所以,在循环输出字符的过程中,应该使用  *((*p)[ i]+j)  来访问数组  array[ i]  中的字符。而  *(*(*p)[ i]+j)  实际上多了一次额外的解引用,导致访问错误的内存地址,从而无法正确输出字符。

修正后的代码如下:
#include <stdio.h>

int main()
{
    char *array[5] = {"FishC", "Five", "Star", "Good", "WoW"};
    char **p = array; // 将 char *((*p))[5] 替换为 char **p

    int i, j;

    for (i = 0; i < 5; i++)
    {
        for (j = 0; *(*p[ i] + j) != '\0'; j++) // 将 *(*(*p)[ i]+j) 替换为 *((*p)[ i]+j)
        {
            printf("%c ", *(*p[ i] + j));
        }
        printf("\n");
    }
    return 0;
}

这样就可以正确逐个输出字符串的字符了。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-29 09:46:53 | 显示全部楼层
问题描述:

上述代码无法实现字符串字符逐个输出。*(*(*p)[i]+j)代表的是什么意思?为什么将其替换为*((*p)[i]+j)就可以实现了呢?

回答:

*(*(*p)[i]+j)*((*p)[i]+j)都涉及指针操作,表示对指针进行解引用得到的数据。具体解释如下:

1. *(*(*p)[i]+j)的含义:
   - (*p)[i]:首先访问指针p所指向的地址,它是一个指向数组的指针。然后通过索引i访问数组中的第i个元素。
   - *(*(*p)[i]+j):接下来,使用*对上一步得到的数组元素进行解引用,获取指向字符的指针(即字符串的首地址)。最后,通过索引j访问字符串中的第j个字符。

2. *((*p)[i]+j)的含义:
   - (*p)[i]:同样,首先通过指针p的解引用获取指向数组的指针,并通过索引i访问数组中的第i个元素。这一步与上述相同。
   - *((*p)[i]+j):不同的是,在上一步得到的数组元素的基础上,使用*对其进行解引用,获取指向字符的指针。最后,通过索引j访问字符串中的第j个字符。

为什么将*(*(*p)[i]+j)替换为*((*p)[i]+j)就可以实现字符串字符逐个输出呢?

这是因为array[i]是一个字符串(即字符数组),其类型是char*。所以,在表达式中使用*(*(*p)[i]+j)时,*的解引用操作会直接获取字符串中的字符,并输出字符值。而在*((*p)[i]+j)中,去掉了多余的解引用操作,直接获取到了字符串中的字符指针,再通过*来输出字符值。

总结:*(*(*p)[i]+j)*((*p)[i]+j)都能实现逐个输出字符串中的字符,只是操作的层次略有不同。

球一个最佳答案谢谢啦!这对我非常重要!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-7-29 11:07:42 | 显示全部楼层
isdkz 发表于 2023-7-29 09:46
首先,我们来解释一下  *(*(*p)[ i]+j)  和  *((*p)[ i]+j)  这两个表达式的含义:

1.  *(*(*p)[ i]+j)  ...

char*(*p)[5] = &array,那(*p)[]里存放的是否是字符的地址的地址呢?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-29 11:15:55 | 显示全部楼层
WUHESAN 发表于 2023-7-29 11:07
char*(*p)[5] = &array,那(*p)[]里存放的是否是字符的地址的地址呢?

是的,(*p)[5]本身就是一个指针数组,存放的是字符地址的地址。这里表示(*p)指向的是一个长度为5的指向char类型数据的指针数组。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-7-29 11:22:03 | 显示全部楼层
isdkz 发表于 2023-7-29 11:15
是的,(*p)[5]本身就是一个指针数组,存放的是字符地址的地址。这里表示(*p)指向的是一个长度为5的指向ch ...

那么能否这样推算,(*p)[5]是地址的地址,*((*p)[5])+j是地址,*(*((*p)[5])+j)即printf要打印的字符?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-7-29 11:25:10 | 显示全部楼层
WUHESAN 发表于 2023-7-29 11:22
那么能否这样推算,(*p)[5]是地址的地址,*((*p)[5])+j是地址,*(*((*p)[5])+j)即printf要打印的字符?


[b]不完全正确。(*p)[5]是一个指针数组,存放的是地址,而不是地址的地址。(*p)[5]表示的是数组中的第五个元素。*((*p)[5])+j是将第五个元素的地址加上j,这个结果并不一定是一个有效的地址,因为这个操作可能会越界。*(*((*p)[5])+j)是对这个可能越界的地址进行解引用,这个操作可能会导致程序崩溃。如果你想要获取第i个字符串的第j个字符,应该这样写:*((*p)[i] + j)。[/b]
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-10-7 11:28

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表