指针到指针的算术
有人可以解释以下代码的输出吗
char* a[] = {"ABC123", "DEF456", "GHI789"};
char **p = a;
cout<<++*p<<std::endl;
cout<<*p++<<std::endl;
cout<<++*p<<std::endl;
输出:
BC123
BC123
EF456
让我感到困惑的是 ++*p 和 *p++ 的不同行为。我期望输出是:
ABC123
DEF456
GHI789
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
也许这会有所帮助。您的示例大致相当于:
没有括号,
*p++
被解析为*(p++)
因为后缀增量的优先级高于解引用运算符。不过,在整个表达式之后仍然会进行增量。另一方面,前缀增量和 * 具有相同的优先级,因此
++*p
从右到左解析为++(*p)
。知道前缀增量必须在表达式之前完成,您现在可以将整个图片放在一起。Perhaps this will help. You example is roughly equivalent to this:
Without parentheses,
*p++
is parsed as*(p++)
since suffix increment has got higher precedence than dereference operator. Increment is still done after the whole expression, though.On the other hand, prefix increment and * have got same precedence, so
++*p
is parsed right-to-left as++(*p)
. Knowing that prefix increment has to be done before the expression, you can now put the whole picture together.第 1 行第一个
*p
将指向数组"ABC123"
中的元素,++
向前移动一个,因此 'BC123 ' 被打印。在第 2 行,
*p
仍然指向BC123
,因此会打印该内容,然后在打印后执行++
。这会将指针移动到数组中的第二个元素。在第 3 行,它与第 1 行相同。您已获取
p
的内容(现在是数组中的第二个元素),并将一个字符移动到该字符串,从而打印EF456
(也可以看看这里字符串类型数组上的指针算术,C++如何处理这个?因为我认为了解正在发生的事情可能很有用)
要打印您期望的内容,以下内容会起作用:
或者
或各种其他方式(考虑到其他人所说的优先级)
On line 1 first
*p
will be pointing to the element in the array"ABC123"
and the++
moves one forward and so 'BC123' is printed.On line 2
*p
is still pointing toBC123
so this is printed and then once printed the++
is carried out. This moves the pointer to the 2nd element in the arrayOn line 3 it is the same as line 1. You have taken the contents of
p
(Now the 2nd element in the array) and moved one character in that string, thus printingEF456
(Also have a look at here Pointer arithmetic on string type arrays, how does C++ handle this? as I think it might be useful to get an understanding of what is happening)
To print what you expected the following would work:
Or
Or various other ways (taking into account precedence as others have said)
根据C++运算符优先级表,后自增运算符的优先级高于解引用(*)运算符,预自增和解引用运算符的优先级相同。预递增和解引用运算符也是从右到左关联的。
因此,在第一行 (
cout<<++*p<) 中,* 和 ++ 从右向左计算(首先取消引用,然后递增)。现在 p 仍然指向第一个数组(因为它没有改变),但是 (*p) 指向第一个字符串的第二个字母(输出显示了这一事实)。
在第二行 (
cout<<*p++<) 中,首先计算后增量(在检索
p
的旧值之后) >) 并且p
递增,现在指向第二个数组。但在递增之前,p 的值用于表达式中,第二行的输出与第一行完全相同。在第三行中,首先对
p
进行取消引用(指向第二个数组的第一个字母),然后递增(指向第二个数组的第二个字母),并打印该值。According to C++ operator precedence table, precedence of post-increment is higher than dereference (*) operator, and pre-increment and dereference operator have same precedence. Also pre-increment and dereference operator are right-to-left associative.
So in the first line (
cout<<++*p<<std::endl;
), * and ++ are evaluated from right to left (first dereference, then increment). Nowp
still point to the first array (because it has not changed),but (*p) points to the second letter of the first string (the output shows this fact).In second line (
cout<<*p++<<std::endl;
) however post-increment is evaluated first (after retrieving the old value ofp
) and thep
is incremented and now points to the second array. But before increment, the value of p is used in the expression and output of the second line is exactly as the first line.In third line, first the
p
is dereferenced (point to the first letter of the second array), then incremented (point to the second letter of the second array), and the value is printed.++*p
在打印之前执行。所以增加指针,然后打印。*p++
打印后执行。打印,然后递增。++*p
is executed before printing. So increment pointer, then print.*p++
is executed after printing. Print, then increment.只是一个猜测,但我认为因为您正在使用
cout<<++*p< 增加引用指针,所以您实际上所做的是增加p 指向的字符串的开头,然后将其输出到标准输出。
类似地,cout<<*p++<在输出后递增字符,因此最终的
cout<<++*p< 产生两个增量。
你应该尝试这个,看看它是否有效
Just a guess, but I think because you are incrementing the deferenced pointer using
cout<<++*p<<std::endl;
, what you are actually doing is incrementing the character at the start of the string that p points to then outputting this to the standard output.Similarly
cout<<*p++<<std::endl;
is incrementing the character after outputting so the finalcout<<++*p<<std::endl;
results in two increments.You should try this instead and see if it works