如何使C++编译器遵循与C#在该赋值语句中相同的优先级、关联性和求值顺序

How to make the C++ compiler to follow the same precedence, associativity and order of evaluation that C# has in the this assignment statement?

本文关键字:优先级 关联性 顺序 赋值语句 编译器 C++ 何使      更新时间:2023-10-16

考虑以下代码:

int x = 1;
int y = 2;
y = x + (x = y);

当这在C#中运行时,变量最终被分配了以下值:

x=2

y=3

另一方面,当同样的程序在C++中运行时,变量的结尾是这样的:

x=2

y=4

显然,C++编译器使用的优先级关联性评估顺序规则与C#不同(如Eric Lippert的文章中所解释的(。

所以,问题是:

是否可以重写赋值语句以强制C++进行与C#相同的求值

唯一的限制是将其作为一个衬垫。我知道这可以通过将作业分成两行来重写,但目标是将其保持在一行中。

是的,这确实是可能的。

x = (y+=x) - x;

这么简单。

是否可以重写赋值语句以强制C++像C#一样求值?

是。为了澄清,C#中的规则是,大多数情况下,表达式的左侧在右侧之前完全求值。所以C#保证+左边的x的评估发生在右边的x = y的副作用之前。C++不作此保证;编译器可能对这个表达式的含义意见不一。

(挑战:我说"大多数"是有原因的。举一个C#中的一个简单表达式的例子,左边的副作用是在右边的副作用之后执行的。(

我知道这可以通过将分配拆分为两行来重写

右。你希望有一个有两个副作用的语句:用x的原始值增加y,并将y的原始值赋给x。所以你可以把它写成

int t = y;
y = y + x;
x = t;

但是:

目标是将其保持在一行中。

我认为"line"的意思是"statement"。好的只需使用逗号运算符。

int t = ((t = y), (y = y + x), (x = t));

很简单。我不知道你为什么要。我想这是一个谜题,旨在引出关于你是否知道逗号运算符的信号。

额外学分:那份报表中需要多少括号?


超级奖励:如果我们不想使用逗号运算符怎么办?我们可以使用其他运算符作为排序运算符。

int t = ((t = y) & 0) || ((y = y + x) & 0) || (x = t);

我们执行||的左边,结果是false,所以我们执行右边,以此类推

类似地,((expr1) & 0) ? 0 : (expr2)保证expr1expr2之前运行。

基本上,这里需要的是保证许多子表达式按特定顺序发生。查找"序列点",看看C和C++中的哪些运算符产生序列点;您可以使用它们对表达式进行排序,因此得名。

您可以编写:

int x = 1;
int y = 2;
y = std::exchange(x,y) + y;

但高度不受欢迎。你甚至不得不停止浏览,想想这个简单的操作。