在函数参数中使用前缀和后缀运算符时的不同和奇怪的结果 [duplicate]

Different and odd results when using prefix and postfix operators in function arguments [duplicate]

提问人:Vishesh Mehta 提问时间:4/24/2021 最后编辑:anastaciuVishesh Mehta 更新时间:4/24/2021 访问量:96

问:

法典:

#include <stdio.h>

int main()
{
    int i = 3;
    printf("%d %d %d %d %d\n",i = 7,--i,i = 18, i+5, i = 0);
    printf("%d %d %d %d %d\n",i = 7,i--,i = 18, i+5, i = 0);

    return 0;
}  

输出:

7 7 7 5 7
7 18 7 5 7

为什么我得到这个输出,谁能向我解释一下语句中的这些表达式是如何执行的?printf

我的意思是,编译器按哪个顺序考虑?

c printf stdio 前缀运算符

评论

1赞 PaulMcKenzie 4/24/2021
我的意思是编译器以什么顺序考虑 printf 语句中的这些表达式——没有定义的顺序。函数参数可以在 C++ 中以任何顺序计算。但是,你为什么要考虑编写这样的代码呢?
0赞 Vishesh Mehta 4/24/2021
它是否取决于编译器到编译器?
0赞 PaulMcKenzie 4/24/2021
它可能取决于用于构建代码的不同编译器选项,而不仅仅是不同的编译器。不要这样写代码,这是底线。
0赞 PaulMcKenzie 4/24/2021
另外,请标记一种语言。C 和 C++ 是两种不同的语言。
0赞 0___________ 4/24/2021
这是一个 veru 常见的骗局

答:

0赞 MrFthiz 4/24/2021 #1

这是一个非常奇怪的代码,你永远不应该渴望写这样的代码,它会带来不必要的混乱。

函数参数可以按任何顺序计算,具体取决于编译器设置,因此此代码的输出可能因编译器和设置而异。

我假设你在某个学校课堂上看到过这段代码,这种类型的例子通常在教师试图解释后增量和前增量时出现。

请理解增量前和增量后的差异拳头:

  • ++x(pre-increment)表示“递增变量;的值 表达式是最终值”
  • x++(post-increment)表示“记住原始值,然后 递增变量;表达式的值为原始值 值”

编辑:更改解释以免引起混淆,输出可能会因多个变量而异。

评论

0赞 PaulMcKenzie 4/24/2021
这种类型的例子通常出现在教师试图解释后增量和增量前时——如果这是所显示的内容,那么该教师应该被解雇,并试图解释输出已经完成。
1赞 anastaciu 4/24/2021 #2

这里最大的问题是,由于缺少序列点,在调用中所做的更改会调用未定义的行为。i

一个表现出未定义行为的程序对编译过程应该如何发生没有要求,编译器可以按照它认为合适的方式处理它,不同的编译器甚至同一编译器的不同版本将产生不同的结果。

虽然这不是必需的,但他们通常做的一件事是生成一些警告,前提是启用了警告标志,有些甚至不需要它,演示

相关标准条目:

N1570 ISO/IEC 9899:201x C11

§6.5 表达式:

2 - 如果标量对象上的副作用相对于同一标量对象上的不同副作用或使用同一标量对象的值计算未排序,则行为未定义。如果表达式的子表达式有多个允许的排序,则如果在任何排序中出现这种未排序的副作用,则行为是未定义的。

需要明确的是,逗号运算符不是序列点。

我还应该注意,函数参数的计算顺序是未指定的。

§6.5.2.2 函数调用

10 - 在函数指示符和实际参数的计算之后,但在实际调用之前有一个序列点。调用函数(包括其他函数调用)中的每个计算,如果在执行被调用函数的主体之前或之后没有专门排序,则相对于被调用函数的执行进行不确定的排序。

如前所述,这不是您应该向任何人展示的代码,在这种情况下,这是出于学习目的。

1赞 molbdnilo 4/24/2021 #3

参数的计算顺序是未指定的,对同一对象的未排序修改具有未定义的行为。

因此,从形式上讲,对你的代码进行推理是没有意义的。

但是,它可以通过正确的评估来解释,而不是非理性或随机的。
(请注意,大多数参数与传递相同; “是”,而不是 18。
ii = 18i

第一个:

i = 0;
int new_variable = i + 5;
i = 18;
i -= 1;
i = 7;
printf("%d %d %d %d %d\n", i, i, i, new_variable, i);

第二个:

i = 0;
int new_variable = i + 5;
i = 18;
int previous_i = i;
i = 7;
printf("%d %d %d %d %d\n", i, previous_i, i, new_variable, i);
i -= 1;