在编程语言中扩展预增量运算符[重复]
Posted
技术标签:
【中文标题】在编程语言中扩展预增量运算符[重复]【英文标题】:Expanding pre increment operator in programming languages [duplicate] 【发布时间】:2013-12-16 09:49:14 【问题描述】:例如,i++
可以写成i=i+1
。
同理,++i
如何写成如上i++
的形式?
是否和i++
一样,或者如果不一样,请在上面i++
的表格中指定++i
的正确写法?
【问题讨论】:
i++
和 ++i
的含义可以根据上下文而改变,例如foo(i++)
和 foo(++i)
不太一样。
这些也取决于语言,因此请具体说明您要问的语言是什么
i++
不等同于i =i+1
。表达式i++
的值是 i before 增量的值。表达式++i
的值是i 在递增之后的值,因此表达式++i
的值是表达式i = i+1
的值。
i++ = i+1 所以 ++i = 1+i 我是对的吗?(开个玩笑)
【参考方案1】:
实际上你的方法是错误的:
i=i+1
更接近于++i
而不是i++
这样做的原因是它无论如何只会对周围的表达式产生影响,例如:
j=++i
赋予 j 与 j=(i+=1)
和 j=(i=i+1)
相同的值
不过,这个故事还有很多内容:
1) 同理,我们来看看前置增量和后置增量的区别:
j=i++
与 j=++i
第一个是post-increment(返回值并且“post”=afterwards increments),后一个是pre-increment (值是“pre”=先增加,然后返回)
因此,(多语句)等价物将是:
分别为j=i; i=i+1;
和i=i+1; j=i;
这使得整个事情变得非常有趣,使用像 j=++i++
这样的(理论上的)表达式(尽管在标准 C 中这是非法的,因为你不能在一个语句中多次更改一个变量)
关于内存栅栏也很有趣,因为现代处理器可以这样做,称为乱序执行,这意味着,您可以按特定顺序编写代码,并且它可能以完全不同的顺序执行(尽管有当然有一些规则)。编译器也可能会重新排序您的代码,因此这 2 条语句最终实际上是相同的。
-
2) 根据您的编译器,在编译/优化等之后,表达式很可能是相同的。
如果您有i++;
和++i;
的独立表达式,编译器很可能会将其转换为中间的'ADD' asm 命令。您可以使用大多数编译器自己尝试,例如使用 gcc 是 -s
来获取中间 asm 输出。
此外,多年来,编译器倾向于优化非常常见的构造
for (int i = 0; i < whatever; i++)
因为在这种情况下直接翻译 i++
会破坏一个额外的寄存器(并可能导致寄存器溢出)并导致不需要的指令(我们在这里谈论的东西非常小,它真的不会除非循环使用单个 asm 指令或类似指令运行数万亿次)
-
3)回到你原来的问题,整个事情都是一个优先问题,因为这两个陈述可以表示为(这次比上面的解释更准确一点):
something = i++
=> temp = i; i = i + 1; something = temp
和
something = ++i
=> i = i + 1; something = i
(在这里你也可以看到为什么第一个变体理论上会导致更多的寄存器溢出和更多的指令)
正如您在此处看到的那样,第一个表达式不能轻易地以我认为可以满足您的问题的方式进行更改,因为不可能使用优先符号来表达它,例如括号,或者更容易理解的块)。不过对于第二个,这很简单:
++i
=> (++i)
=> i = i + 1; return i
(伪代码)
第一个是
i++
=> return i; i = i + 1
(又是伪代码)
如您所见,这是行不通的。
希望我能帮助你澄清你的问题,如果有什么需要澄清或我犯了错误,请随时指出。
【讨论】:
【参考方案2】:技术上j = ++i
是一样的
j = (i = i + 1);
和j = i++;
是一样的
j = i;
i = i + 1;
你可以避免用这个技巧把它写成两行,虽然 ++ 不这样做。
j = (i = i + 1) - 1;
【讨论】:
【参考方案3】:++i
和 i++
如果作为独立语句编写(而不是将其与其他操作链接起来),则两者的结果相同。
该结果也与i += 1
和i = i + 1
相同。
只有在更大的表达式中开始使用 ++i
和 i++
时才会出现差异。
【讨论】:
【参考方案4】:这个前后增量的真正含义,你只会知道你在哪里使用它。?
主要区别是
在执行任何语句之前,前置条件将首先递增。 后置条件将在语句执行后递增。
这里我给你提了一个简单的例子。
void main()
int i=0, value;
value=i++; // Here I've used post increment. Here value of i will be assigned first then It'll be incremented.
// After this statement, now Value will hold the value 0 and i will hold the value 1
// Now I'm going to use pre increment
value=++i; // Here i've used pre increment. So i will be incremented first then value will be assigned to value.
// After this statement, Now value will hold the value 2 and i will hold the value 2
【讨论】:
【参考方案5】:这可以使用匿名方法完成:
int i = 5;
int j = i++;
相当于:
int i = 5;
int j = new Func<int>(() => int temp = i; i = i + 1; return temp; )();
但是,如果将其扩展为带有 ref
参数的命名方法(它模仿 i++
运算符的底层实现)会更有意义:
static void Main(string[] args)
int i = 5;
int j = PostIncrement(ref i);
static int PostIncrement(ref int x)
int temp = x;
x = x + 1;
return temp;
【讨论】:
【参考方案6】:i++
没有“等价物”。
在 i++
中,i
的值在计算完周围的表达式后递增。
在 ++i
和 i+1
中,i
的值在计算周围的表达式之前递增。
【讨论】:
【参考方案7】:++i 将增加 'i' 的值,然后返回增加的值。 示例:
int i=1;
System.out.print(++i);
//2
System.out.print(i);
//2
i++ 会增加 'i' 的值,但会返回 'i' 在增加之前持有的原始值。
int i=1;
System.out.print(i++);
//1
System.out.print(i);
//2
【讨论】:
我确定,您的意思是第二个代码 sn-p 中的i++
。
我认为您的回答有点误导,因为在执行语句之后(即当程序处于注释时)i
的值是 2 无论您使用的是 i++
还是++i
。如果您在访问时使用此语句,则只有区别,例如arr[i++]
和 arr[++i]
不返回相同元素的数组。
@mvieghofer 这就是我返回增量值或原始值的意思。在那一行中,当我们使用 ++i 或 i++ 时,返回值会有所不同,之后,两个值将相同。
好的,但是你写的方式可能会让读者感到困惑(至少让我感到困惑)以上是关于在编程语言中扩展预增量运算符[重复]的主要内容,如果未能解决你的问题,请参考以下文章
在 sizeof(++n) 表达式中未调用增量运算符 [重复]