c += c-- | ++b;

來源:互聯網
上載者:User

標籤:blog   http   使用   strong   2014   問題   

一切都是從這開始的

一個大一學弟通過QQ給我發來一個C++的題:

int c = 8, b = 3;c += c-- | ++b;

問c的值是多少。通過筆算得到c為19,然後隨手建了個C#控制台項目跑了一下,悲劇了。。。C#輸出的為20。重新筆算一遍還是19啊,趕緊重建立了一個C++控制台項目跑出的結果為19。到底為什麼C++和C#會不一樣呢?

求證1

通過網上查資料得知,是C#求值順序的問題,具體是怎麼樣的情況呢?我們來反組譯碼一下:

    .method private hidebysig static void  Main(string[] args) cil managed    {      .entrypoint      // Code size       33 (0x21)      .maxstack  4      .locals init ([0] int32 c,               [1] int32 b)      IL_0000:  nop      IL_0001:  ldc.i4.8      IL_0002:  stloc.0      IL_0003:  ldc.i4.3      IL_0004:  stloc.1      IL_0005:  ldloc.0      IL_0006:  ldloc.0      IL_0007:  dup      IL_0008:  ldc.i4.1      IL_0009:  sub      IL_000a:  stloc.0      IL_000b:  ldloc.1      IL_000c:  ldc.i4.1      IL_000d:  add      IL_000e:  dup      IL_000f:  stloc.1      IL_0010:  or      IL_0011:  add      IL_0012:  stloc.0      IL_0013:  ldloc.0      IL_0014:  call       void [mscorlib]System.Console::WriteLine(int32)      IL_0019:  nop      IL_001a:  call       valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()      IL_001f:  pop      IL_0020:  ret    } // end of method Program::Main

通過IL代碼我們可以清晰的看到他的計算過程:

  • 0~4行 為變數賦值Call Stack裡0為變數c值為8,1為變數b值為3
  • 5行 緩衝了c的值,放到了Evaluation Stack裡,緩衝的值為8
  • 6行 緩衝了一個c值,緩衝的值為8
  • 7~a行 執行了c=c-1,此時c值為7
  • b~f行 執行了b=b+1,並留了一個副本,值為4
  • 10行 6行緩衝的數8和b~f行中留的4做or,值為12
  • 11行10行中結果12再加5行中緩衝的8結果為20
  • 12行儲存到變數c中

c += c-- | ++b; 等價於 c = c + (c-- | ++b);,通過反組譯碼我們可以看出:

  1. C#的求值順序為從左至右不會因為運算順序改變,等號右側第一個c的值在一開始就緩衝了。
  2. c--在求值之後立刻就進行了結算,c變數此時值變為了7,但是c變數的值並不影響算式最終的結果,原因見1。
  3. 把算式變為c = c + (--c | ++b);得到的值為15(8+(7|4)),反組譯碼後觀察,結論同第一條,c--和--c隻影響了括弧中的運算結果。

根據上面結論我們把算式改成c = (c-- | ++b) + c;,得到的結果為19。

求證2

那麼C++到底是怎麼執行的呢?繼續,反編譯之:

(反組譯碼的程式基於VS2013的C++ Debug編譯結果,GCC 4.6.1的反組譯碼代碼略有區別,執行過程一致,結論僅限定在這兩個編譯環境下)C++的執行過程:

  1. 使用eax寄存器做b=b+1
  2. 使用ecx寄存器做c=8+(8|4)(此時b=4)
  3. 使用edx寄存器做c=c-1

從反組譯碼可以看出:

  • C++不會緩衝數值,C++也沒有規定求值順序。
  • C++在計算的時候才取值,所以c = (c-- | ++b) + c;的結果還是19。
  • C++是在整個算式結束的時候才進行的c--,也就是說之所以結果是19不是20,不是因為先算括弧中的or造成最後的加法中的c為7,而是因為c--是在算式賦值結束後才進行結算。(老師們,你們教對了嗎?)

最後驗證一下,改變算式為c = c * 2 + (c-- | ++b);C++的輸出結果為27,8*2+12=28-1=27,反組譯碼也可以看到最後才執行的sub,圖就不上了。

最後
  • 如果你在學C++,千萬不要用C#來驗證你的作業題答案。。。
  • 就讓‘++’這種東西只出現在for語句中吧。。。
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.