隨筆 - 9  文章 - 21  trackbacks - 0
          <2008年5月>
          27282930123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          常用鏈接

          留言簿(1)

          隨筆分類(9)

          隨筆檔案(9)

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          第 5 天的問題

          下面的程序是對兩個十六進(jìn)制(hex)字面常量進(jìn)行相加,然后打印出十六進(jìn)制的結(jié)果。這個程序會打印出什么呢?

          public class JoyOfHex {
              public static void main(String[] args) {
                  System.out.println(Long.toHexString(0x100000000L + 0xcafebabe));
              }
          }
          

          第 5 天問題的解答

          看起來很明顯,該程序應(yīng)該打印出1cafebabe。畢竟,這確實就是十六進(jìn)制數(shù)字10000000016與cafebabe16的和。該程序使用的是long型運算,它可以支持16位十六進(jìn)制數(shù),因此運算溢出是不可能的。

          遺憾的告訴你,結(jié)果是cafebabe,并沒有任何前導(dǎo)的1。這個輸出表示的是正確結(jié)果的低32位,但是不知何故,第33位丟失了。

          原因

          十進(jìn)制字面常量具有一個很好的屬性,即所有的十進(jìn)制字面常量都是正的,而十六進(jìn)制或是八進(jìn)制字面常量并不具備這個屬性。

          要想書寫一個負(fù)的十進(jìn)制常量,可以使用一元取反操作符(-)連接一個十進(jìn)制字面常量。以這種方式,你可以用十進(jìn)制來書寫任何int或long型的數(shù)值,不管它是正的還是負(fù)的,并且負(fù)的十進(jìn)制常數(shù)可以很明確地用一個減號符號來標(biāo)識。

          但是十六進(jìn)制和八進(jìn)制字面常量并不是這么回事,它們可以具有正的以及負(fù)的數(shù)值。如果十六進(jìn)制和八進(jìn)制字面常量的最高位被置位了,那么它們就是負(fù)數(shù)。在這個程序中,數(shù)字0xcafebabe是一個int常量,它的最高位被置位了,所以它是一個負(fù)數(shù)。它等于十進(jìn)制數(shù)值-889275714。

          該程序執(zhí)行的這個加法是一種"混合類型的計算(mixed-type computation)。左操作數(shù)是 long 類型的,而右操作數(shù)是 int 類型的。為了執(zhí)行該計算,Java將int類型的數(shù)值用拓寬原始類型轉(zhuǎn)換提升為一個long類型,然后對兩個long類型數(shù)值相加。因為int是一個有符號的整數(shù)類型,所以這個轉(zhuǎn)換執(zhí)行的是符合擴展,它將負(fù)的int類型的數(shù)值提升為一個在數(shù)值上相等的long類型數(shù)值。

          解決辦法

          System.out.println(Long.toHexString(0x100000000L + 0xcafebabeL));
          

          這個加法的右操作數(shù)0xcafebabe被提升為了long類型的數(shù)值0xffffffffcafebabeL。這個數(shù)值之后被加到了左操作數(shù)0x100000000L上。當(dāng)作為int類型來被審視時,經(jīng)過符號擴展之后的右操作數(shù)的高32位是-1,而左操作數(shù)的高32位是1,將這兩個數(shù)值相加就得到了0,這也就解釋了為什么在程序輸出中前導(dǎo)1丟失了。

          第 5 天問題的總結(jié)

          這個題給我們的教訓(xùn)是:混合類型的計算可能會產(chǎn)生混淆,尤其是十六進(jìn)制和八進(jìn)制字面常量無需顯式的減號符號就可以表示負(fù)的數(shù)值。為了避免這種窘境,通常最好是避免混合類型的計算

          對于語言的設(shè)計者們來說,應(yīng)該考慮支持無符號的整數(shù)類型,從而根除符號擴展的可能性。可能會有這樣的爭辯:負(fù)的十六進(jìn)制和八進(jìn)制字面常量應(yīng)該被禁用,但是這可能會挫傷程序員,他們經(jīng)常使用十六進(jìn)制字面常量來表示那些符號沒有任何重要含義的數(shù)值。


          今天的問題

          轉(zhuǎn)型被用來將一個數(shù)值從一種類型轉(zhuǎn)換到另一種類型。下面的程序連續(xù)使用了三個轉(zhuǎn)型。那么它到底會打印出什么呢?

          public class Multicast {
              public static void main(String[] args) {
                  System.out.println((int) (char) (byte) -1);
              }
          }
          
          
          posted on 2008-05-17 17:52 李四飛刀 閱讀(1583) 評論(2)  編輯  收藏 所屬分類: 每日一題

          FeedBack:
          # re: 第 6 天: 解答 -- 16進(jìn)制的趣事, 問題 -- 轉(zhuǎn)型 2008-05-19 12:55 草兒
          你是不是建議我們都去買一本 《Java 解惑》?   回復(fù)  更多評論
            
          # re: 第 6 天: 解答 -- 16進(jìn)制的趣事, 問題 -- 轉(zhuǎn)型 2008-05-21 16:29 d
          很無聊!!!!!!!,如果你寫過c++,你說的都是入門基礎(chǔ)!  回復(fù)  更多評論
            
          主站蜘蛛池模板: 建水县| 怀柔区| 镇远县| 墨竹工卡县| 阿巴嘎旗| 临湘市| 靖边县| 黄大仙区| 柘荣县| 横峰县| 勃利县| 长丰县| 万荣县| 敦煌市| 蓬溪县| 根河市| 甘泉县| 兴宁市| 新和县| 津市市| 大庆市| 简阳市| 昌黎县| 涟源市| 广西| 长子县| 永城市| 嵩明县| 酉阳| 崇文区| 青浦区| 四平市| 奉新县| 郧西县| 德格县| 南乐县| 黄梅县| 长汀县| 祁门县| 九龙城区| 西和县|