gpt4 book ai didi

c++ - 指针表达式 : *ptr++, *++ptr 和++*ptr

转载 作者:行者123 更新时间:2023-12-01 16:34:22 30 4
gpt4 key购买 nike

最近我遇到了这个我自己无法理解的问题。
这三个表达式有什么用是什么意思?

*ptr++
*++ptr
++*ptr
我试过里奇。但不幸的是,他无法理解他讲述的这 3 次手术。
我知道它们都是为了增加指针/指向的值而执行的。我也可以猜测可能有很多关于优先级和评估顺序的事情。就像先增加指针然后获取该指针的内容一样,一个简单地获取内容然后增加指针等等。如您所见,我对他们的 没有清楚的了解。实际操作,我想尽快清除。但是当我有机会在程序中应用它们时,我真的迷失了。例如:
int main()
{
char *p = "Hello";
while(*p++)
printf("%c",*p);
return 0;
}
给我这个输出:
ello
但我的期望是它会打印 Hello .
最后一个请求——请举例说明每个表达式在给定代码片段中的工作方式。因为大多数时候只有一小段理论会飞过我的脑海。

最佳答案

这里有一个详细的解释,我希望会有所帮助。让我们从您的程序开始,因为它最容易解释。

int main()
{
char *p = "Hello";
while(*p++)
printf("%c",*p);
return 0;
}
第一条声明:
char* p = "Hello";
声明 p作为指向 char 的指针.当我们说“指向 char 的指针”时,这是什么意思?这意味着 p 的值是 char 的地址; p告诉我们在内存中的哪个位置留出了一些空间来保存 char .
该语句还初始化 p指向字符串文字中的第一个字符 "Hello" .为了这个练习,理解 p 很重要。不是指向整个字符串,而是指向第一个字符, 'H' .毕竟 p是一个指针 char ,而不是整个字符串。 p的值是 'H'的地址在 "Hello" .
然后你设置一个循环:
while (*p++)
循环条件是什么 *p++是什么意思?这里有三件事情在起作用,使这个令人费解(至少在熟悉之前):
  • 两个运算符的优先级,后缀++和间接*
  • 后缀增量表达式的值
  • 后缀增量表达式的副作用

  • 1. 优先级 .快速浏览运算符的优先级表会告诉您,后缀增量的优先级 (16) 比取消引用/间接 (15) 的优先级更高。这意味着复杂的表达式 *p++将被分组为: *(p++) .也就是说, *部分将应用于 p++ 的值部分。所以让我们拿 p++首先部分。
    2.后缀表达式值 . p++的值是 p 的值在增量之前。如果你有:
    int i = 7;
    printf ("%d\n", i++);
    printf ("%d\n", i);
    输出将是:
    7
    8
    因为 i++计算结果为 i在增量之前。同样 p++将计算为 p 的当前值.众所周知,当前值 p'H'的地址.
    所以现在 p++ *p++ 的一部分已评估;它是 p 的当前值.然后是 *部分发生。 *(current value of p)表示:访问 p持有的地址处的值.我们知道那个地址的值是 'H' .所以表达式 *p++计算结果为 'H' .
    现在等一下,你是说。如 *p++计算结果为 'H' ,为什么不 'H'在上面的代码中打印?这就是副作用的来源。
    3.后缀表达式副作用 .后缀 ++具有当前操作数的值,但它具有增加该操作数的副作用。嗯?看看那个 int再次代码:
    int i = 7;
    printf ("%d\n", i++);
    printf ("%d\n", i);
    如前所述,输出将是:
    7
    8
    i++在第一个 printf() 中评估,它的计算结果为 7。但是 C 标准保证在第二个 printf() 之前的某个时间点开始执行, ++ 的副作用运算符将发生。也就是说,在第二个 printf()之前发生, i将作为 ++ 的结果增加第一个 printf() 中的运算符.顺便说一下,这是标准给出的关于副作用时间的少数保证之一。
    那么,在你的代码中,当表达式 *p++被评估,它评估为 'H' .但是当你达到这个目的时:
    printf ("%c", *p)
    那个讨厌的副作用已经发生了。 p已增加。哇!它不再指向 'H' , 但要过去一个字符 'H' : 到 'e' ,换句话说。这解释了你笨拙的输出:
    ello
    因此,其他答案中的有用(和准确)建议的合唱:打印收到的发音 "Hello"而不是它的 cockney 对应物,你需要类似的东西
    while (*p)
    printf ("%c", *p++);
    这么多。剩下的呢?你询问这些的含义:
    *ptr++
    *++ptr
    ++*ptr
    我们刚刚讲了第一个,那么我们来看第二个: *++ptr .
    我们在之前的解释中看到后缀增量 p++有一定的优先级、值(value)和副作用。前缀增量 ++p具有与其后缀对应项相同的副作用:它将其操作数增加 1。但是,它具有不同的优先级和不同的值。
    前缀增量的优先级低于后缀;它的优先级为 15。换句话说,它与解引用/间接操作符 * 具有相同的优先级。 .像这样的表达
    *++ptr
    重要的不是优先级:两个运算符的优先级相同。所以结合性开始了。前缀增量和间接运算符具有左右结合性。由于这种关联性,操作数 ptr将与最右边的运算符 ++ 分组在操作符更靠左之前, * .换句话说,表达式将被分组 *(++ptr) .因此,与 *ptr++ 一样但出于不同的原因,这里也是 *部分将应用于 ++ptr 的值部分。
    那么这个值是多少呢?前缀增量表达式的值是增量后的操作数的值。这使它成为与后缀增量运算符非常不同的野兽。假设你有:
    int i = 7;
    printf ("%d\n", ++i);
    printf ("%d\n", i);
    输出将是:
    8
    8
    ...与我们在后缀运算符中看到的不同。同样,如果您有:
    char* p = "Hello";
    printf ("%c ", *p); // note space in format string
    printf ("%c ", *++p); // value of ++p is p after the increment
    printf ("%c ", *p++); // value of p++ is p before the increment
    printf ("%c ", *p); // value of p has been incremented as a side effect of p++
    输出将是:
    H e e l                // good dog
    你明白为什么吗?
    现在我们得到你问的第三个表达式, ++*ptr .实际上,这是最棘手的。两个运算符具有相同的优先级和左右结合性。这意味着表达式将被分组 ++(*ptr) . ++部分将应用于 *ptr 的值部分。
    所以如果我们有:
    char q[] = "Hello";
    char* p = q;
    printf ("%c", ++*p);
    令人惊讶的自负输出将是:
    I
    什么?!好的,所以 *p部分将评估为 'H' .然后是 ++开始发挥作用,此时,它将应用于 'H' ,根本不是指针!将 1 添加到 'H' 会发生什么?你得到 1 加上 'H' 的 ASCII 值, 72;你得到 73。将其表示为 char ,你会得到 char ASCII 值为 73: 'I' .
    这会处理您在问题中询问的三个表达式。这是您问题的第一条评论中提到的另一个:
    (*ptr)++ 
    那一个也很有趣。如果你有:
    char q[] = "Hello";
    char* p = q;
    printf ("%c", (*p)++);
    printf ("%c\n", *p);
    它会给你这个热情的输出:
    HI

    这是怎么回事?同样,这是一个优先级、表达式值和副作用的问题。由于括号, *p部分被视为主要表达式。主要表达胜过其他一切;他们首先得到评估。和 *p如您所知,计算结果为 'H' .表达式的其余部分, ++部分,应用于该值。所以,在这种情况下, (*p)++变成 'H'++ . 'H'++的值是多少?如果你说 'I' ,你已经忘记(已经!)我们关于后缀增量的值(value)与副作用的讨论。记住, 'H'++计算为 'H' 的当前值.所以先 printf()正在打印 'H' .然后,作为副作用, 'H'将增加到 'I' .第二个 printf()打印 'I' .还有你愉快的问候。
    好的,但在最后两种情况下,为什么我需要
    char q[] = "Hello";
    char* p = q;
    为什么我不能有类似的东西
    char* p = "Hello";
    printf ("%c", ++*p); // attempting to change string literal!
    因为 "Hello"是字符串文字。如果您尝试 ++*p ,您正在尝试更改 'H'在字符串中到 'I' ,制作整个字符串 "Iello" .在 C 中,字符串文字是只读的;尝试修改它们会调用未定义的行为。 "Iello"英语中也未定义,但这只是巧合。
    相反,你不能有
    char p[] = "Hello";
    printf ("%c", *++p); // attempting to modify value of array identifier!
    为什么不呢?因为在这种情况下, p是一个数组。数组不是可修改的左值;您无法更改位置 p通过前置或后置递增或递减指向,因为数组的名称就像一个常量指针一样工作。 (实际情况并非如此;这只是一种方便的查看方式。)
    总结一下,这里是你问的三件事:
    *ptr++   // effectively dereferences the pointer, then increments the pointer
    *++ptr // effectively increments the pointer, then dereferences the pointer
    ++*ptr // effectively dereferences the pointer, then increments dereferenced value
    这是第四个,和其他三个一样有趣:
    (*ptr)++ // effectively forces a dereference, then increments dereferenced value
    如果 ptr,第一个和第二个会崩溃实际上是一个数组标识符。如果 ptr,第三个和第四个会崩溃指向字符串文字。
    你有它。我希望现在一切都是 Crystal 。你一直是一个很棒的观众,我整个星期都会在这里。

    关于c++ - 指针表达式 : *ptr++, *++ptr 和++*ptr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18481740/

    30 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com