2016-04-27 59 views
8

我發現這個例子,任何人都可以解釋這裏發生了什麼?我正在使用LLVM 7.1。C移位行爲

uint8_t a = 0xff; 
a = ~a >> 1; 
// a = 0b1000000 

uint8_t b = 0xff; 
b = ~b; 
b = b >> 1; 
//b = 0 

a and b should be equal ??

編輯: 添加拆卸:

testt`main: 
    0x100000f70 <+0>: pushq %rbp 
    0x100000f71 <+1>: movq %rsp, %rbp 
    0x100000f74 <+4>: xorl %eax, %eax 
    0x100000f76 <+6>: movl $0x0, -0x4(%rbp) 
    0x100000f7d <+13>: movl %edi, -0x8(%rbp) 
    0x100000f80 <+16>: movq %rsi, -0x10(%rbp) 
    0x100000f84 <+20>: movb $-0x1, -0x11(%rbp) 
    0x100000f88 <+24>: movzbl -0x11(%rbp), %edi 
    0x100000f8c <+28>: xorl $-0x1, %edi 
    0x100000f8f <+31>: sarl $0x1, %edi 
    0x100000f92 <+34>: movb %dil, %cl 
    0x100000f95 <+37>: movb %cl, -0x11(%rbp) 
    0x100000f98 <+40>: movb $-0x1, -0x12(%rbp) 
    0x100000f9c <+44>: movzbl -0x12(%rbp), %edi 
    0x100000fa0 <+48>: xorl $-0x1, %edi 
    0x100000fa3 <+51>: movb %dil, %cl 
    0x100000fa6 <+54>: movb %cl, -0x12(%rbp) 
    0x100000fa9 <+57>: movzbl -0x12(%rbp), %edi 
    0x100000fad <+61>: sarl $0x1, %edi 
    0x100000fb0 <+64>: movb %dil, %cl 
    0x100000fb3 <+67>: movb %cl, -0x12(%rbp) 
    0x100000fb6 <+70>: popq %rbp 
    0x100000fb7 <+71>: retq 
+1

不,他們不_should_。實現定義的行爲。沒有足夠的信息給出。看看彙編器的輸出。 – Olaf

+0

'a和b應該相等'爲什麼?代碼是不同的。 –

+0

@Olaf:爲什麼它實施defiend?無符號整數的右移很好嗎?如果它已經簽名,那將是UB ... – Jimbo

回答

10

在第一種情況下~a晉升爲int,讓您得到:

a = 0xffffff00 >> 1 = 0x7fffff80 

被截斷爲0x80

在第二種情況下,截斷髮生之前移位,這樣就可以獲得:

b = 0xffffff00 

其被截斷爲0x00,然後移這給出0x00的結果。

(注:上述假定32個整數,正常2S補碼錶示和邏輯右帶符號的值的偏移。)

+1

只適用於32位「int」(可能)並且僅用於2的補碼(可能)。另外,不推薦'〜a',而是'a'。 '〜'已經在'int'上完成了。 – Olaf

+0

謝謝@Olaf - 我會爲此添加註釋。 –

+2

哇,相當令人印象深刻,謝謝:) – iCaramba