背景
我被一位朋友问过以下谜题:
void fn(void)
{
/* write something after this comment so that the program output is 10 */
/* write something before this comment */
}
int main()
{
int i = 5;
fn();
printf("%d\n", i);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我知道可以有多个解决方案,一些涉及宏,一些假设有关实现和违反C.
我感兴趣的一个特定解决方案是对堆栈做出某些假设并编写以下代码:(我知道它是未定义的行为,但可能在许多实现中按预期工作)
void fn(void)
{
/* write something after this comment so that the program output is 10 */
int a[1] = {0};
int j = 0;
while(a[j] != 5) ++j; /* Search stack until you find 5 */
a[j] …Run Code Online (Sandbox Code Playgroud) 特别是,前缀运算符的引用返回对我有意义 - 如果有人想对对象进行进一步的操作,它是有用的.
但是,我无法理解为什么后缀运算符被设计为按值返回.
它只是一个约定,还是有一个很好的理由为什么它是这样设计的(就像返回值对后缀没有意义,但对前缀有意义)?
谁能解释一下?
回答
由于下面的答案,似乎后缀运算符不一定必须按值返回(根据标准).
但是,由于后缀运算符的语义要求(返回原始值,但之后将引用增加到原始值),并结合以下标准要求:
操作符重载是函数,因此所有副作用必须在函数完成之前发生.
正如David Rodriguez在下面清楚解释的那样,将价值分叉似乎是语义要求的必然结果.
在这种情况下,由于我们返回另一个值(不是原始引用,因为它将通过函数的右括号更改),返回其他值by-value似乎最有意义.