括号和赋值运算符顺序

时间:2015-12-27 17:57:03

标签: c# c++

我正在编写c表达式解析器并发现我不明白的行为:

#include <iostream>
#include <sstream>

int main()
{
    std::string string1;
    std::string string2 = std::string((string1 = std::string("first")) + " " + (string1 = std::string("second")));

    std::cout << string1 << std::endl;
    std::cout << string2 << std::endl;

    int int1;
    int int2 = (int1 = 1) + (int1 = 2);

    std::cout << int1 << std::endl;
    std::cout << int2 << std::endl;

    std::cin.get();

    return 0;
}

输出:

first
first first
2
4

我原以为:

second
first second
2
3

在C#中运行相同的程序时,我得到了预期的输出。你能解释一下那里发生了什么吗?

C#代码:https://gist.github.com/Kukkimonsuta/59543cfc4f7f73b8bebd

2 个答案:

答案 0 :(得分:7)

此代码在C ++中具有未定义的行为,因为单个表达式对同一变量产生多个副作用(即,string1的两个赋值)。 int1变量也是如此。

在您的情况下,编译器将按照与您预期相反的顺序应用这两个副作用。即使它按照您预期的顺序应用它们,该程序仍然无效。

  

在C#中运行相同的程序时,我得到了预期的输出。

与C ++不同,C#并没有给编译器开发人员留下太多的决定。这些表达式的评估顺序以及在C ++中产生未定义行为的许多其他表达式都由语言标准很好地定义。

答案 1 :(得分:5)

这是C和C ++中未定义的行为。变量int1在同一语句中被多次修改。

请参阅Sequence point

  

一个经常被引用的例子是C表达式i=i++,它显然都赋予i以前的值并递增i ....在C和C ++中,评估这样的表达式产生未定义的行为。

和脚注:

  

C99规范的第6.5#2条:&#34; 在上一个和下一个序列点之间,对象的存储值最多只能通过表达式的计算修改一次。此外,只能访问先前值以确定要存储的值。&#34;

除此之外,假设我们有不同的变量,结果仍然无法保证。 C ++没有指定表达式部分的评估顺序contrary to C#