printf和cout有什么区别?

3

以下是类似于下面这样的一些代码:

int x = 1;
printf("%d,%d,%d",x,x++,x);  //A  statement
cout<<x<<x++<<x<<endl; //B statement

我知道执行顺序是从右到左,那么为什么语句A的结果是“1,1,1”,而语句B的结果是“112”?
我使用的是VS2008。 在调试模式下:结果相同:2,1,2。 在发布模式下:结果不同:A: 1,1,1,B: 1,1,2。

7
你的问题标签很好地回答了整个主题。 - WhozCraig
6
有很多不同之处。但在这两种情况下,你都会引起未定义行为。 - Adam Rosenfield
1
“我知道执行顺序是从右到左的。” - 你知道吗?这很有趣,因为标准与此不同。 - Ed S.
1
如果你真的感兴趣,这里有一个关于序列点的绝佳问答:https://dev59.com/Zm855IYBdhLWcg3wuG-W。 - WhozCraig
1
@KinjalPatel:请参阅C99 §7.19.3/7:“[...]仅当可以确定流不是指向交互式设备时,标准输入和标准输出流才是完全缓冲的。” - Adam Rosenfield
显示剩余6条评论
4个回答

1
你使用 printf 的方式会导致未定义的行为。函数参数的求值顺序是未指定的。它们甚至不必以离散单元进行评估,因为一个表达式的一部分可以被评估,然后另一部分也可以被评估。这意味着,如果您对评估顺序有某些依赖关系,则整个表达式可能变得未定义。
对于调用 coutoperator <<,情况也是如此。 << 不是序列点。在 cout 的不同子句的评估顺序完全未指定。由于您在 printf 示例中具有相同类型的依赖关系,因此在此处也会引发未定义的行为。
因此,您可能会得到两个表达式的相同结果。您可能会得到不同的结果。当您评估它们之一时,守护程序可能会飞出您的鼻子。你无法知道。
序列点和评估顺序的主题可能相当复杂。如果您想了解更多信息,我建议您查看这个问题:

3
@EdS:是的,这是UB(未定义行为)——逗号在这里不是序列点(它们是函数参数分隔符,而不是逗号运算符)。 - Adam Rosenfield
1
@AdamRosenfield:天啊,我甚至没有想到那个,我一直在关注参数评估顺序。在回答了1000多个“为什么x++ + ++x不起作用?”的问题后,我真的应该看到它。你是对的。然而,这一点是错误的 - “函数参数的评估顺序是未定义的。” - Ed S.
@EdS.,它是未定义的。我们只能确定在进入函数之前所有参数都已被评估。 - Anish Ramaswamy
@EdS.,好的,我刚刚看到你提到它是未指定而不是未定义。是的,我的错误。 - Anish Ramaswamy
@Omnifarious:是的,抱歉,当我意识到我完全忽略了另一个问题后,我本可以更清楚地表达。 - Ed S.
显示剩余2条评论

0

语句A和B的结果相同。

        int x = 1;
        printf("%d,%d,%d",x,x++,x);  //A  statement
        //cout<<x<<x++<<x<<endl; //B statement
        return 0;

语句A

     int x = 1;
    //printf("%d,%d,%d",x,x++,x);  //A  statement
    cout<<x<<","<<x++<<","<<x<<endl; //B statement
    return 0;

语句 B

结果/行为与编译器不一致。


5
结果有时是相同的。这里的使用实际上会引发未定义行为。这意味着它可能按照您想要的方式工作,但也可能完全做出其他操作。 - Cody Gray
我使用带有调试模式的vs2008:结果相同:2,1,2。使用发布模式:结果不同:A:1,1,1,B:1,1,2。 - guyuequan
1
@guyuequan:这是因为标准中没有指定正确的结果。事实上,你很幸运你的程序没有崩溃或出现其他问题。 - Omnifarious

0

使用printf时,在调用printf之前会评估所有参数(x=1)。 使用cout时,参数按顺序评估和应用。 (至少就您的编译器而言)


3
补充一些细节,cout是基于流的,这就是为什么参数会按顺序进行评估和应用的原因。 - Rohit
3
这个答案完全错误。 - Omnifarious
编辑以反映这是这个特定编译的工作方式。 - levis501

0

请查看本文。 这是一篇好文章。

文章是重复的。

但是,如果我们谈论printf()cout<<, 在执行printf语句时,它会获取变量的最后一个更改的值,并且还会将更改的值影响到下一个语句,而不是当前语句。

而在cout语句中,变量的最新值被取出,因此直接影响当前语句。

希望您清楚了解。


1
尽管这理论上可以回答问题,但最好在此处包含答案的基本部分,并提供参考链接。这样即使您包含的链接将来会有问题,也能确保您的答案保持实用性。 - Cody Gray
这个问题的标题应该改变,因为它涉及概念性问题而不是技术性问题。 - AB Bolim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接