2012-02-20 69 views
5

有人可以解释下面的代码的输出指向指针运算

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 
+6

运算符优先级。添加一些括号,它会明白... – jrok 2012-02-20 10:21:32

回答

3
char* a[] = {"ABC123", "DEF456", "GHI789"}; 
char **p = a; 
cout<<++*p<<std::endl; // 1 
cout<<*p++<<std::endl; // 2 
cout<<++*p<<std::endl; // 3 

在第一行第一*p将指向所述元件的阵列"ABC123"中和++移动一个前进等等“BC123”被打印。

在线2 *p仍然指向BC123所以这是打印,然后一旦打印++进行。这将指针移至数组中的第二个元素

在第3行上它与第1行相同。您已获取p(现在是数组中的第2个元素)的内容并移动了该字符串中的一个字符,因此,印刷EF456

(也可以看看在这里Pointer arithmetic on string type arrays, how does C++ handle this?,因为我认为,要了解眼前发生的事情的理解,它可能是有用的)

要打印你所期望的下面将工作:

cout<<*p++<<std::endl; 
cout<<*p++<<std::endl; 
cout<<*p++<<std::endl; 

或者

cout<<*p<<std::endl; 
cout<<*(++p)<<std::endl; 
cout<<*(++p)<<std::endl; 

或各种其他方式(考虑到优先正如其他人所说)

0

++*p在打印前执行。所以增加指针,然后打印。打印后执行 *p++。打印,然后增加。

0

只是一个猜测,但我认为,因为你正在使用cout<<++*p<<std::endl;递增推理指针,你实际上做的是递增字符串开始处的字符数,然后把它输出到标准输出。

同样cout<<*p++<<std::endl;正在输出后递增字符,因此最终的cout<<++*p<<std::endl;结果为两个增量。

而应该试试这个,看看它是否工作

cout<<*(++p)<<std::endl; 
cout<<*(p++)<<std::endl; 
cout<<*(++p)<<std::endl; 
+1

该输出的最后一行导致它不幸地出现繁荣。 '++ p'将它移动到数组的末尾 – Firedragon 2012-02-20 11:00:12

4

也许这会有所帮助。您的例子就是大致相当于此:

++(*p); 
cout << *p << '\n'; 

cout << *p << '\n'; 
++p; 

++(*p); 
cout << *p << '\n'; 

没有括号,*p++被解析为*(p++)因为后缀增量已经得到了比引用操作更高的优先级。尽管如此,增量仍然是在整个表达式之后完成的。

另一方面,前缀增量和*具有相同的优先级,所以++*p被从右向左解析为++(*p)。知道前缀增量必须在表达式之前完成,现在可以将整个图片放在一起。

+0

我明白了......我只是将运算符优先级放到图片中,完全忘记了关联性..谢谢 – 2012-02-20 10:50:54

1

根据C++运算符优先级表,后置增量优先级高于解引用(*)运算符,前置增量和解引用运算符优先级相同。另外预增和取消引用操作符是从右到左的关联。

所以在第一行(cout<<++*p<<std::endl;)中,*和++从右到左评估(先取消引用,然后增加)。现在p仍然指向第一个数组(因为它没有改变),但(* p)指向第一个字符串的第二个字母(输出显示了这个事实)。

在第二行(cout<<*p++<<std::endl;)中,首先评估后增量(在检索旧值p后),并且p递增,现在指向第二个数组。但是在增量之前,p的值用在表达式中,第二行的输出与第一行完全一样。

在第三行中,首先解除引用p(指向第二个数组的第一个字母),然后递增(指向第二个数组的第二个字母),并打印该值。