*++*++ppp,*++pp[1],*++(*(1+ppp)有啥具体的区别吗?(C/C++指针问题)

Posted

技术标签:

【中文标题】*++*++ppp,*++pp[1],*++(*(1+ppp)有啥具体的区别吗?(C/C++指针问题)【英文标题】:*++*++ppp, *++pp[1], *++(*(1+ppp) Is there any specific difference?(C/C++ pointer problem)*++*++ppp,*++pp[1],*++(*(1+ppp)有什么具体的区别吗?(C/C++指针问题) 【发布时间】:2019-11-16 10:16:36 【问题描述】:
#include <cstdio>
using namespace std;

int main()

    const char *p[] =  "aa", "bb", "cc" ;
    const char **pp[] =  p + 2, p + 1, p ;
    const char ***ppp = pp;

    printf("%s\n", **++ppp );  // bb
    printf("%s\n", *++*++ppp);  // bb
    printf("%s\n", *++pp[1]);   // cc
    // printf("%s\n", *++(*(1+ppp)));   wrong

    return 0;


Microsoft VS2015 输出: bb bb 抄送 执行异常:0xC0000005

*++*++ppp,*++pp[1],*++(*(1+ppp)有具体区别吗? *++ppp不是pp[1]吗?不是*++ppp 不是*(1+ppp) 吗? 谢谢!

【问题讨论】:

在 C++ 中,char *p[] 必须是 const char *p[](或者我个人最喜欢的 char const* p[] 首先编译它并阅读警告。 为什么是*++(*(1+ppp))); wrong *++*++ppp, *++pp[1], *++(*(1+ppp) 任何写这种表达式的人都应该被终身禁止编程:) 如果你以人类可读和可理解的形式编写操作,你会更好地理解它,而不是这种“伪智能”棘手的简写方式。如果一个人需要思考超过 2 秒才能理解表达式 - 这是编码风格不佳的标志。糟糕的编码风格会导致错误。 【参考方案1】:

TL;DR:是的,*++pp[1] 之间存在很大差异。前者在取消引用之前增加指针,后者取消引用指向元素之后的元素。返回的值是一样的,但是在第一种情况下指针改变了


重要提示:永远不要在生产代码中写出这样的行!您可以在实验代码和傻瓜代码中做到这一点。但专业代码必须清晰易懂。

我知道一些风格指南禁止在其他表达式中使用增量运算符。他们必须各自为政。


让我们剖析一下你的所有行,看看它们对你的变量做了什么。

printf("%s\n", **++ppp ); // *(*(++p))

ppp 递增并指向pp[1]。那是内容指向p+1,它指向打印的"bb"。检查。

printf("%s\n", *++*++ppp); // *(++(*(++ppp)))

ppp 再次递增并指向pp[2]。取消引用和预增量让它指向p+1。那是内容指向打印的"bb"。检查。

printf("%s\n", *++pp[1]); // *(++(pp[1]))

这一次你增加pp[1],它指向p+2pp 本身不能递增,因为它是一个数组,所以 pp[1] 会递增。好的,p+2 指向打印出来的"cc"。检查。

printf("%s\n", *++(*(1+ppp))); // *(++(*(1+ppp)))

总和1+ppp 指向pp[3],它在数组pp 之后。请记住,您之前将ppp 增加了两次!取消引用此指针是未定义的行为,可以传递任何值。然后将该值解释为指向const char ** 的指针,您尝试再次对其进行递增和取消引用。此处某处会导致指针无效,因此会引发分段错误。轰隆隆。


您可以通过以下方式调查您的问题以了解指针和指针数组的工作原理:

#include <cstdio>
using namespace std;

void print_pointers(const char *p[], const char **pp[], const char ***ppp)

    printf("p   = %p : %p %p %p\n", p, p[0], p[1], p[2]);
    printf("pp  = %p : %p %p %p\n", pp, pp[0], pp[1], pp[2]);
    printf("ppp = %p\n", ppp);


int main()

    const char *p[] =  "aa", "bb", "cc" ;
    const char **pp[] =  p + 2, p + 1, p ;
    const char ***ppp = pp;

    print_pointers(p, pp, ppp);
    printf("%s\n", **++ppp );  // bb
    print_pointers(p, pp, ppp);
    printf("%s\n", *++*++ppp);  // bb
    print_pointers(p, pp, ppp);
    printf("%s\n", *++pp[1]);   // cc
    print_pointers(p, pp, ppp);

    const char ***p1 = 1+ppp;
    printf("      1+ppp   = %p\n", p1);
    const char **p2 = *p1;
    printf("    *(1+ppp)  = %p\n", p2);
    ++p2;
    printf(" ++(*(1+ppp)) = %p\n", p2);
    const char *p3 = *p2;
    printf("*++(*(1+ppp)) = %p\n", p3);
    printf("%s\n", p3); // printf("%s\n", *++(*(1+ppp)));

    return 0;

【讨论】:

非常感谢,忘了第一个"printf("%s\n", **++ppp);",ppp自己加了1;所以我总是想到第二个 "printf("%s\ n", *++*++ppp); "应该输出 "cc"

以上是关于*++*++ppp,*++pp[1],*++(*(1+ppp)有啥具体的区别吗?(C/C++指针问题)的主要内容,如果未能解决你的问题,请参考以下文章

项目管理将成PPP模式发展新“命门”!

判断任意一点是否在矩形内(矩形可能与坐标轴有一定夹角)

Juniper JunOS PPPOE配置

《夜深人静写算法》数论篇 - (21) 威尔逊定理

H5 类选择器

以下代码片段 C++ 的说明