C-对++i和i++的不解

发布于 2016-11-24 10:17:28 字数 261 浏览 1337 评论 13

看到一道c笔试题,如下,

#include <stdio.h>

int main(void)
{
int a[] = {6, 7, 8, 9, 10};
int *p = a;
*(p++) += 123;
printf("%d, %dn", *p, *(++p));
return 0;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

夜无邪 2017-10-16 10:12:24

请参考C语言运算符优先级和结合性。

灵芸 2017-10-01 16:06:54

原因一:
printf函数是一个可变参数的C函数,在VC等绝大多数C编译器中,默认情况下,参数进栈的顺序是从右向左。
故:对于此题,在printf函数栈中,首先压入栈的是:(++p) (值为8),其次压入栈的是:p(值为8);
输出结果的时候,最先出栈当然是栈顶元素,故输出的结果是:8,8;
原因二:当然是 ++i 和 i++ 的区别,这个楼上的同学都给了很详尽解释;

个人的想法:我觉得要做这个题目 ,首先我们要对++i 和 i++ 很熟悉,当然这还不能正确地解答出这道题目,其次就是对函数参数进栈的了解。
我以前遇到过 cout<< 这种输出的问题,跟提问题者出现的情况是一样的 ,当时不知道是什么原因,后来想想应该和printf一样。
有兴趣的同学可以试一试~~~

灵芸 2017-09-02 01:06:19

i++是先运行结束之后再自增,++i是先自增再运算

晚风撩人 2017-08-19 07:28:20

1、i++是先参与计算,再自增1;++i是先自增1,在参与计算
2、输出结果都是8的原因:
#include <stdio.h>
int main(void)
{
int a[] = {6, 7, 8, 9, 10};
int p = a;
*(p++) += 123;
printf("%d, %d, %d, %dn", *p, *(++p),
(++p),*p);
return 0;
}
输出为:9,9,8,7
这个结果说明,实参在传递到printf函数中时,是从右向左计算实参表达式,所以输出的结果都是第三个元素8.

甜柠檬 2017-08-16 01:16:23

一般编译器对函数参数求值是从右向左,最右的是++p 所以p先指向了8,然后就相当于打印两次*p了

晚风撩人 2017-08-03 10:40:17

i++的机制是:先参与其他运算再自增。
++i,是先自增后参与运算。所以:

#include <stdio.h>

int main(void)
{
inta[] = {6, 7, 8, 9, 10};
//这里p指向首地址,对应6
int *p = a;
//先将首地址对应的6加123变为了129,然后p++,p指针地址自增,指向7
*(p++) += 123;
//printf参数压栈顺序从右向左,++p后这个指针p指向了8,所以出栈输出的时候就是8,8
printf("%d, %dn", *p, *(++p));
return 0;
}

i++、++i的机制加上出入栈的顺序决定了p指向的地址,这个输出就成了8,8。

甜柠檬 2017-06-11 12:11:41

++i是直接在原变量上增加1,先自增然后参与其他的运算。
i++的过程中生成了一个临时变量。参与其他运算的时候还是i自增前的值。

你看看他们二者底层的实现了就明白了的。这是摘自《C++ Primer(第三版)》上的代码:

复数类型的++操作符的前置和后置可能的实现:
(complex本身并没有提供++操作符的实现)

前置:

 inline complex<double>&
operator++(complex<double> &cval)
{
return cval += complex<double>(1);
}

后置:

 inline complex<double>
operator++(complex<double> &cval,int)
{
complex<doble> oldval = cval;
cval += complex<double>(1);
return oldval;
}

浮生未歇 2017-06-10 21:36:00

问题的关键是:
printf的输出顺序是自右向左,而不是自左向右。

浮生未歇 2017-04-24 13:40:56

a=1;
b=++a;
c=a++;
结果是b=2,c=1
原理a先自加,再赋值给b;而c是a先赋值给c,然后a再自加
a=1,b=2,c=3;
a+=b;//a=a+b;a最后为3
b-=c;//b=b-c;b最后为-1
这个就是原理,来理解一下吧希望你满意!

甜柠檬 2017-04-06 17:57:58

程序相当于下面的程序, ++p是先加再返回加后的p, p++是先临时保存p的指向,然后p向后移动,再返回临时保存的, 而printf先执行了++p,所以打印的都是第三个元素

 #include <stdio.h>

int main(void)
{
int a[] = {6, 7, 8, 9, 10};
int *p = a;
//*(p++) += 123;
*p += 123;
p = p + 1;
//printf("%d, %dn", *p, *(++p));
p =p+1;
printf("%d,%dn",*p,*p);
for (int i = 0;i <5;i++)
{
printf("%dn",a[i]);
}

return 0;
}

灵芸 2017-03-07 17:48:04

完完全全的undefined behavior
*(p++) += 123; 这句首先就是个undefined behavior.
这是C++03关于这句话的诠释,不多解释,耐心的自己看。
4. Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified.53) Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored.The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression; otherwise the behavior is undefined.

printf("%d, %dn", *p, *(++p)); 这句话是另外一个undefined behavior
函数参数的入栈顺序我们可以看作是固定的,但是,没有规定每个参数的evaluation和side effect发生的顺序是固定的,在每个参数求值得之间,是不存在sequence point的

偏爱自由 2017-01-29 20:34:11

printf从右至左进行运算

虐人心 2016-12-28 12:43:22

这个其实和编译器是有关的,有可能换了其他编译器,换了优化选项,结果都会变。
对于大多数编译器来说参数从右到左求值,是因为__stdcall和__cdecl调用约定都是将参数从右到左压栈的,有个对于编译器来说顺手的先后次序的问题(右边先求值比较顺手)。不过这个在C和C++标准里似乎都没有规定,特殊情况下也有可能因为优化而改变了求值的顺序的(因为没有规定求值顺序必须和压栈顺序一样啊)。
不过我也没仔细读过C和C++标准,如果真的在哪里规定了的话求纠正。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文