2016-04-27 13 views
8

Tôi tìm thấy ví dụ này, bất cứ ai có thể giải thích những gì đang xảy ra ở đây? Tôi đang sử dụng LLVM 7.1.Hành vi bithifting C

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

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

ab cần được bình đẳng ??

EDIT: Added tháo gỡ:

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

Không, chúng _should_ không. Thực hiện hành vi được xác định. Không đủ thông tin. Có một cái nhìn tại đầu ra Assembler. – Olaf

+0

'a và b phải bằng nhau' tại sao? Mã này khác. –

+0

@Olaf: Tại sao nó lại hoạt động? Một sự thay đổi đúng của một số nguyên unsigned là tốt chắc chắn? Nếu nó đã được ký, nó sẽ là UB ... – Jimbo

Trả lời

10

Trong trường hợp đầu tiên ~a được thăng int, vì vậy bạn sẽ có được:

a = 0xffffff00 >> 1 = 0x7fffff80 

được cắt ngắn để 0x80.

Trong trường hợp thứ hai, cắt ngắn xảy ra trước sự thay đổi, vì vậy bạn sẽ có được:

b = 0xffffff00 

được cắt ngắn để 0x00, và sau đó thay đổi này mang lại một kết quả của 0x00.

(Lưu ý: ở trên giả định 32 bit int, biểu diễn bổ sung 2 giây bình thường và dịch chuyển đúng giá trị đã ký.)

+1

Chỉ dành cho 32 bit 'int' (có thể) và chỉ cho phần bù 2 (có thể). Ngoài ra, không phải '~ a' được quảng cáo, nhưng' a'. '~' đã được thực hiện trên 'int'. – Olaf

+0

Cảm ơn @Olaf - Tôi sẽ thêm ghi chú vào hiệu ứng này. –

+2

wow, khá ấn tượng, cảm ơn :) – iCaramba