关于printf中的参数的计算次序的问题。

关于printf中的参数的计算次序的问题。

请看下面的程序:

int main(int argc, char* argv[])
{
int j;
j=10;
printf(" %d %d \n",j=2*3,j*5);
j=10;
printf(" %d %d \n",(j=2*3,j*5),j*8);
j=10;
printf(" %d %d \n",(j=2*3,j*5),j*8,j=100);
return 0;
}

//输出分别为

6 50
30 48
500 800

十分不解,请高手指教,谢谢。

图片说明
我在cb上运行了一下,你输出结果就有问题呀

如果我没记错的话,输出时是从右往左去看的
你查一下资料看看看

1.逗号运算符:从左到右结合,(a,b);取最后一个值b。
2.而printf语句从右向左计算。

更正一下答案:(在网友的友情提醒下,发现我之前的回复是错误的。目前已更正,感谢贵阳老马马善福专业维修游泳池堵漏防水工程的贡献!)

1)函数值参求值因为早于参数表压栈,并且值参的计算顺序在C/C++标准中没有明确规定,因此取决于编译器的实现。即不同编译器的计算顺序存二义性,因此应尽量避免使用side effect副作用表达式作为函数参数。
【之前的答案,也是错误的答案!】1)C/C++默认函数参数表继承了汇编的栈操作,且值参为运行时动态求值。因此编译器按,运行时动态从函数调用堆栈中依次解析传入的参数,即从右至左顺序执行。

2)逗号表达式是一种运算符,返回值为最后一条子语句的值,并且逗号表达式的结合性为L-R,即从左至右的顺序执行本条语句。

自我诫勉博文
https://blog.csdn.net/hslbloc/article/details/101695188

函数的参数的求值顺序,是未定义行为,也就是说,不同的编译器编译产生的代码,结果不同。
当你的参数是副作用表达式的时候,则相同的源代码,编译出来的程序,结果不可控,因此这种写法要杜绝
作为学校老师,让学生研究这个或者以此出题分析运算结果纯属误人子弟
关于未定义行为,参考:
https://blog.csdn.net/pegasuswang_/article/details/12872797
https://blog.csdn.net/baihacker/article/details/9204429


鉴于有一个钻牛角尖的用户一直在评论区刷屏,特别追加如下:

维基百科(需要科学上网)出处:
https://en.wikipedia.org/wiki/Unspecified_behavior

Order of evaluation of subexpressions[edit]

Many programming languages do not specify the order of evaluation of the sub-expressions of a complete expression. This non-determinism can allow optimal implementations for specific platforms e.g. to utilise parallelism. If one or more of the sub-expressions has side effects, then the result of evaluating the full-expression may be different depending on the order of evaluation of the sub-expressions.[1] For example, given

a = f(b) + g(b);

, where f and g both modify b, the result stored in a may be different depending on whether f(b) or g(b) is evaluated first.[1] In the C and C++ languages, this also applies to function arguments. Example:[2]

#include <iostream>
int f() {
  std::cout << "In f\n";
  return 3;
}

int g() {
  std::cout << "In g\n";
  return 4;
}

int sum(int i, int j) {
  return i + j;
}

int main() {
  return sum(f(), g()); 
}

The resulting program will write its two lines of output in an unspecified order.[2] In other languages, such as Java, the order of evaluation of operands and function arguments is explicitly defined.[7]

简单解释下,在这个程序里,输出In g和In f的顺序是不确定的,可能先输出前者,也可能先输出后者。这是因为作为函数参数,f()和g()的求值顺序不确定

不关副作用表达式的事,也不关参数如何入栈(由Calling convention调用约定决定),一个函数的参数入栈当然是固定的,否则调用者和被调用者如何协调一致。

之所以求值顺序不确定,是为了代码的优化,比如
foo(a+b, a+b);
编译器可以优化成
c = a + b;
foo(c,c);
这里还有更复杂的情况,比如
foo(a() + b(), a(), a() + c);
编译器可以有多种优化,比如
_p2 = a();
_p1 = _p2 + b();
_p3 = _p2 + c;
foo(_p1, _p2, _p3);
因为a()在多个参数中公用,所以编译器调整参数求值顺序,先求它。显然,这里的参数的求值顺序规则就非常复杂,所以干脆C规范就对此不做规定,任由编译器“发挥”。

这是为什么参数求值顺序是不确定的根本原因

这里涉及"求值顺序"。表达式中子表达式的求值顺序,以及函数参数的求值顺序,C++语言标准没有明确规定。不能假定按从左到右的顺序或某种特定的顺序求值。以怎样的顺序求值,不同的编译器的实现方式可能不同。参考下面的例子:

int f1(int& x) { x += 1; printf("f1, x = %d\r\n", x); return x; }
int f2(int& x) { x *= 2; printf("f2, x = %d\r\n", x); return x; }
int f3(int& x) { x *= x; printf("f3, x = %d\r\n", x); return x; }
int g(int x1, int x2, int x3) { return x1 + x2 + x3; }

int main()
{
    int x = 2;
    int y1 = g(f1(x), f2(x), f3(x));    // 不能确定编译器以怎样的顺序求值f1(x)、f2(x)和f3(x).
    x = 2;
    int y2 = f1(x) + f2(x) + f3(x);     // 不能确定编译器以怎样的顺序求值f1(x)、f2(x)和f3(x).
    printf("%d, %d\r\n", y1, y2);       // y1和y2可能结果不同.
}

不同于函数参数列表,内建(非用户定义)的逗号运算符按从左到右的顺序求值,并返回最右边的表达式的值。参考下面的代码:

    x = 2;
    int y3 = (x += 1, x *= 2, x *= x);  // y3 =36, x = 36
    x = 2;
    int y4 = (f1(x), f2(x), f3(x));     // y4 = 36, x = 36

有关求值顺序的详细内容,请参考:https://zh.cppreference.com/w/cpp/language/eval_order