C#解惑27: 變幻莫測的i值

來源:互聯網
上載者:User

謎題27: 變幻莫測的i值
    你的任務仍舊是要指出這個程式將列印什麼。
    class Shifty
    {
      static void Main()
      {
        int i = 0;
        while (-1 << i != 0)
          i++;
        System.Console.WriteLine(i);
      }
    }

解惑27: 變幻莫測的i值
    常量-1是所有32位都被置位的int數值(0xffffffff)。左移操作符將0移入到由移位所空出的右邊最低位,因此運算式(-1 << i)將最右邊的i位設定為0,並保持其餘的32-i位為1。很明顯,這個迴圈將完成32次迭代,因為(-1 << i)對任何小於32的i來說都不等於0。你可能期望在i等於32時終止條件測試返回false,從而使程式列印32,但是它列印的並不是32。實際上,它不會列印任何東西,而是進入了一個無限迴圈。
    問題在於(-1 << 32)等於-1而不是0,因為移位操作符只使用其右運算元的低5位作為移位長度。或者是低6位,如果其左運算元是一個long類型數值[C#語言規範 7.8]。這條規則作用於全部的兩個移位操作符:<<和>>。移位長度總是介於0到31之間,如果左運算元是long類型,則介於0到63之間。這個長度是對32取餘的,如果左運算元是long類型的,則對64取餘。如果試圖對一個int數值移位32位,或者是對一個long數值移位64位,都只能返回這個數值本身。沒有任何移位長度可以讓一個int數值丟棄其所有的32位,或者是讓一個long數值丟棄其所有的64位。
    幸運的是,有一個非常容易的方法能夠修正該問題。我們不是讓-1重複地移位不同的移位長度,而是將前一次移位操作的結果儲存起來,並且讓它在每一次迭代時都向左再移1位。下面這個版本的程式就可以列印我們所期望的32:
    class Shifty
    {
      static void Main()
      {
        int distance = 0;
        for (int val = -1; val != 0; val <<= 1)
          distance++;
        System.Console.WriteLine(distance);
      }
    }
    這個修正過的程式說明了一條普遍的原則:如果可能的話,移位長度應該是常量。如果移位長度緊盯著你不放,那麼你讓其值超過31,或者如果左運算元是long類型的,讓其值超過63的可能性就會大大降低。當然,並不總是可以使用常量的移位長度。當必須使用一個非常量的移位長度時,請確保你的程式可以應付這種容易產生問題的情況,或者根本不會碰到這種情況。
    前面提到的移位操作符的行為還有另外一個令人震驚的結果。很多程式員都希望具有負移位長度的右移操作符可以起到左移操作符的作用,反之亦然。但是情況並非如此。右移操作符總是起到右移的作用,而左移操作符也總是起到左移的作用。負的移位長度通過只保留低5位而去除其他位的方式被轉換成了正的移位長度——如果左運算元是long類型的,則保留低6位。因此,如果要將一個int數值左移,其移位長度為-1,那麼移位的效果是它被左移了31位。
    總之,移位長度是對32取餘的,或者如果左運算元是long類型的,則對64取餘。因此,使用任何移位操作符和移位長度,都不可能將一個數值的所有位全部移走。同時,我們也不可能用右移操作符來執行左移操作,反之亦然。如果可能的話,請使用常量的移位長度,如果移位長度不能設為常量,那麼就要千萬小心。
    語言設計者可能應該考慮將移位長度限制在從0到以位為單位的類型長度的範圍內,並且修改移位長度為類型長度時的語義,讓其返回0。儘管這可以避免在本謎題中所展示的混亂情況,但是它可能會帶來負面的執行結果,因為C#的移位操作符的語義正是許多處理器上的移位指令語義。

    C#解惑總目錄

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.