下面操作结果的解释是什么?
k += c += k += c;
我试图理解以下代码的输出结果:
int k = 10;
int c = 30;
k += c += k += c;
//k=80 instead of 110
//c=70
目前我正在努力理解为什么“k”的结果是 80。为什么分配 k=40 不起作用(实际上 Visual Studio 告诉我该值没有在其他地方使用)?
为什么 k 是 80 而不是 110?
如果我将操作拆分为:
k+=c;
c+=k;
k+=c;
结果是 k=110。
我试图浏览 CIL , 但我对生成的 CIL 的解释不是很深刻,无法获得一些细节:
// [11 13 - 11 24]
IL_0001: ldc.i4.s 10
IL_0003: stloc.0 // k
// [12 13 - 12 24]
IL_0004: ldc.i4.s 30
IL_0006: stloc.1 // c
// [13 13 - 13 30]
IL_0007: ldloc.0 // k expect to be 10
IL_0008: ldloc.1 // c
IL_0009: ldloc.0 // k why do we need the second load?
IL_000a: ldloc.1 // c
IL_000b: add // I expect it to be 40
IL_000c: dup // What for?
IL_000d: stloc.0 // k - expected to be 40
IL_000e: add
IL_000f: dup // I presume the "magic" happens here
IL_0010: stloc.1 // c = 70
IL_0011: add
IL_0012: stloc.0 // k = 80??????
最佳答案
像a op= b;这样的操作等同于a = a op b;。赋值可以用作语句或表达式,而作为表达式它会产生指定的值。你的陈述......
k += c += k += c;
...,因为赋值运算符是右结合的,也可以写成
k += (c += (k += c));
或(展开)
k = k + (c = c + (k = k + c));
10 → 30 → 10 → 30 // operand evaluation order is from left to right
| | ↓ ↓
| ↓ 40 ← 10 + 30 // operator evaluation
↓ 70 ← 30 + 40
80 ← 10 + 70
在整个评估过程中,使用相关变量的旧值。对于 k 的值尤其如此(请参阅我对下面的 IL 的评论和 link Wai Ha Lee 提供的)。因此,您得到的不是 70 + 40(k 的新值)= 110,而是 70 + 10(k 的旧值)= 80。
要点是(根据 C# spec)“表达式中的操作数是从左到右计算的”(操作数是变量 c 和k 在我们的例子中)。这与运算符优先级和结合性无关,在这种情况下,运算符优先级和结合性指示从右到左的执行顺序。 (请参阅本页对 Eric Lippert 的 answer 的评论)。
现在让我们看看 IL。 IL 假定一个基于堆栈的虚拟机,即它不使用寄存器。
IL_0007: ldloc.0 // k (is 10)
IL_0008: ldloc.1 // c (is 30)
IL_0009: ldloc.0 // k (is 10)
IL_000a: ldloc.1 // c (is 30)
堆栈现在看起来像这样(从左到右;堆栈顶部在右边)
10 30 10 30
IL_000b: add // pops the 2 top (right) positions, adds them and pushes the sum back
10 30 40
IL_000c: dup
10 30 40 40
IL_000d: stloc.0 // k <-- 40
10 30 40
IL_000e: add
10 70
IL_000f: dup
10 70 70
IL_0010: stloc.1 // c <-- 70
10 70
IL_0011: add
80
IL_0012: stloc.0 // k <-- 80
请注意,IL_000c: dup、IL_000d: STLoc.0,即对 k 的第一个赋值,可以优化掉。这可能是在将 IL 转换为机器代码时通过抖动对变量完成的。
另请注意,计算所需的所有值要么在进行任何赋值之前被压入堆栈,要么根据这些值计算得出。分配的值(由 STLoc)在此评估期间永远不会重复使用。 STLoc 弹出栈顶。
以下控制台测试的输出是(Release 模式开启优化)
evaluating k (10)
evaluating c (30)
evaluating k (10)
evaluating c (30)
40 assigned to k
70 assigned to c
80 assigned to k
private static int _k = 10;
public static int k
{
get { Console.WriteLine($"evaluating k ({_k})"); return _k; }
set { Console.WriteLine($"{value} assigned to k"); _k = value; }
}
private static int _c = 30;
public static int c
{
get { Console.WriteLine($"evaluating c ({_c})"); return _c; }
set { Console.WriteLine($"{value} assigned to c"); _c = value; }
}
public static void Test()
{
k += c += k += c;
}
关于c# - "k += c += k += c;"中是否有内联运算符的解释?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54674728/
我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou
我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-
给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife
请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是
我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test
我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案
我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que