2016-02-05 42 views
3

我不認爲我完全理解當我左移一個簽名字符時c編譯器中發生了什麼。我正在初始化它的值爲0x8d < < 3,它給了我一個警告:隱式常量轉換中的溢出。我假設這是因爲它爲char提供了太大的價值,但是當我手工完成時,我得到了104個答案。左移溢出

這是否意味着,當值被移出它做

10001101 << 3 = 10001101000 

,而不是

10001101 << 3 = 01101000 

想通了,但是這是代碼:

signed char testChar = 0x8d << 3; 
printf("testChar : %d\n", testChar); 

剛不得不通常初始化它,然後在另一條線上移動它,超級簡單的東西。

+0

警告是正確的,您創建一個編譯時間常量,在創建時溢出字符(8位數量)。 – Rumbleweed

+0

@ M.M:對不起,我誤讀了。 –

+0

請更新您的問題,向我們展示您的實際代碼。此外,你說你有警告,但你沒有告訴我們實際存儲的價值。我期望它是'104'。 –

回答

1

你的問題很困惑:你正在初始化一個值爲0x8d << 3的signed char?這顯然是實現定義的,因爲該值超出了該類型的範圍,並且該類型被簽名。編譯器會發出警告,因爲精度的損失是明確的。

相反,如果你通過意味着左移一個符號的字符,左移一個符號字符具有的0x8d值,這又是不正確的:除非char已超過8位,一個符號的字符不能有一個值的0x8d。它可以具有相同位模式的值-115。左移,這將計算這種方式:

  • char值首先晉升爲int
  • int值向左3但位置偏移:這等同於由8
  • 如果值爲負乘以標準說行爲是不確定的,但使用最2S當前處理器中補充爲負值表示將產生與乘以8相同的結果。

由此產生的值是-920。該值不適用於char。將它存儲到char是實現定義的。最可能的結果是的值爲104

編輯

您發佈的實際代碼:

signed char testChar = 0x8d << 3; 
printf("testChar : %d\n", testChar); 

如果char爲8位,分配具有實現定義的行爲,因爲1128的類型是signed char(-128的範圍之外.. 127),大多數現代處理器的行爲是屏蔽掉高位,並將8個低位存儲到目標字節中,就好像它是一個unsigned char。在你的情況下,結果是1128 & 255 - >104

+0

遐想我對何時使用按位運算符有一個不好的理解。只需將char初始化爲0x8d,然後在另一行上將其轉換,現在打印出正確的答案。 – Lychosand

+1

將'char'初始化爲0x8d不正確,該值超出了signed char的範圍。左移任何數量都是未定義的行爲,因爲該值爲負值,但對於大多數當前處理器,結果與乘以8相同。 – chqrlie

+0

@Lychosand:這並不能解決您的問題。它只是壓制了編譯器警告。 –

0

您還沒有表現出你的實際代碼 (見下文),但您提供足夠的信息來推斷它:

signed char c = 0x8d << 3; 

0x8dint類型。將它左移3位將得到值0x468,或等效地爲1128

初始化將該值從int隱式轉換爲signed char。由於該值超出範圍signed char(推測其範圍爲-128+127,除非您的系統非常奇怪),結果是實現定義的。通常,高位被丟棄,這會產生0x68104的結果。

編譯器警告你,你正在將值1128轉換爲signed char,這個值不夠大。

也許你期待0x8d的類型爲signed char?事實並非如此。表達式的類型幾乎總是由表達式本身決定的,而不是由它出現的上下文決定的。整數常量(十進制,十六進制或八進制)的類型始終爲int,除非它們超過INT_MAX的值,該值至少爲32767(也可能是2147483647)。 (或者,除非他們有像LU後綴,但是這不是與此有關)。

UPDATE:

你告訴我們你的原始代碼:

signed char testChar = 0x8d << 3; 
printf("testChar : %d\n", testChar); 

我期望這會產生警告,因爲您用來初始化testChar的值1128會導致溢出。存儲在testChar中的值是實現定義的,但它很可能是104,即丟棄高位的結果。

如果拆分轉移到一個單獨的任務:

signed char testChar = 0x8d; 
testChar = testChar << 3; 

然後我期望相同的結果。但值0x8d太大而無法存儲在signed char中,因此轉換會生成實現定義的結果 - 最可能是-115。而負值左移有未定義的行爲 - 但同樣,它可能會產生-920,當轉換爲signed char可能會給你104

最終,您的問題的解決方案是做一些事情,而不是你想做的事情。值0x8d << 3將不適合signed char,任何嘗試使其適合將導致問題。通過調整代碼,你可以設法消除編譯器的警告,但是你仍然在做一些沒有道理的事情。

+0

雅你是錢,我瞭解我覺得奇怪的整個範圍的事情,我打算使用一個簽名字符的問題。我仍然給char值0x8d,它正在編譯並給我正確的答案,現在這很奇怪。 – Lychosand

+0

查看我更新的答案。你所做的只是隱藏編譯器的一些信息,所以它不再能夠警告溢出。 –

+0

@chqrlie:處理了Nitpick。 –