2014-06-07 16 views
5

Tôi đã cố gắng chạy mã mã sau:Bitshifting trong C++ sản ​​xuất các câu trả lời sai

char c = (2 << 7) >> 7 

mà nên trở về 0 vì 2 có biểu diễn nhị phân này như một char:

0 0 0 0 0 0 1 0 

Sau 7 thay đổi trái , chúng tôi nhận được

0 0 0 0 0 0 0 0 

Sau đó, sau bảy ca phải, chúng tôi nhận được

0 0 0 0 0 0 0 0 

Tuy nhiên, tôi nhận được kết quả như 2, chứ không phải 0.

Trình biên dịch nói rằng 2 << 7 là 256, nhưng đó là một char và vì vậy nó không phải là 256.

tôi hiểu rằng 2 << 7 sẽ được tính như int s và câu trả lời sẽ được đưa vào c nên 256 >> 7 là 2.

tôi đã cố gắng để cast 2 đến char (ví dụ: (char)2>>7) nhưng nó cũng không hoạt động.

Tôi đang cố gắng để trích xuất từng bit từ char, vì vậy tôi đã viết mã này:

char c = 0x02; 
for(int i=0;i<7;i++) 
{ 
    char current = (c<<i)>>7; 
} 

Làm thế nào tôi có thể nhận được mỗi bit? Có gì sai với cách của tôi?

+6

'2 << 7' * không * a 'char'. –

+2

Vui lòng không thay thế văn bản câu hỏi của bạn bằng "cố định cảm ơn" nếu bạn tìm ra điều gì sai. Thay vào đó, thêm một câu trả lời giải thích những gì đã sai. – templatetypedef

+0

Tôi quên nhưng đây là một bản dupe chắc chắn. – haccks

Trả lời

7

Kết quả của phép dịch số học với một toán hạng là int trong C++ luôn là int. Vì vậy, khi bạn viết

current = (c << i) >> 7; 

C++ sẽ giải thích (c << i)(c << i) >> 7 như int s, đúc trở lại một char chỉ khi việc chuyển nhượng được thực hiện. Vì các giá trị tạm thời là int s, không xảy ra tràn và kết quả sẽ xuất hiện với kết quả nguyên được đúc thành char.

Hy vọng điều này sẽ hữu ích!

+0

các bạn chỉ làm điều đó, ty – MyNick

+0

Làm thế nào đến int để chuyển đổi char (demotion) là không được cảnh báo trong c + +? Tại sao nó không đòi hỏi phải đúc rõ ràng? C++ là loại nghiêm ngặt phải không? – texasbruce

+0

@texasbruce C++ cho phép chuyển đổi tiềm ẩn giữa các loại nguyên thủy nguyên thủy của nó mà không có phôi rõ ràng. Nếu bạn xoay các thiết lập cảnh báo trên trình biên dịch của bạn, bạn có thể nhận được một cảnh báo về nó, mặc dù nó không cần thiết. Trong khi C++ có kiểu gõ tĩnh, vì nó cho phép rõ ràng cho phép các chuyển đổi này, không có lỗi kiểu. – templatetypedef

4

Để nhận được mỗi bit, bạn có thể viết:

(c >> i) & 0x01 

Ưu điểm: Nó hoạt động cho bất kỳ loại số nguyên.

+1

Có đây là cách để thực hiện. Trên một số nền tảng, đây chỉ là một hướng dẫn kiểm tra bit. Chuyển qua giá trị tối đa của loại có thể gọi hành vi không xác định –

4

Theo 5,8 [expr.shift] đoạn 1:

... Các toán hạng phải là kiểu liệt kê không tách rời hoặc unscoped và chương trình khuyến mãi không thể thiếu được thực hiện. Loại kết quả là kết quả của toán hạng bên trái được quảng bá. ...

này cho một cuộc tranh luận trái của loại char cùng với các quy định về khuyến mãi số nguyên (4.5 [conv.prom]) nói rằng kết quả là int. Tất nhiên, một int có thể giữ kết quả của 2 << 7.Bạn có thể dễ dàng xác minh hành vi này, quá:

#include <iostream> 

void print(char c) { std::cout << "char=" << int(c) << "\n"; } 
void print(int i) { std::cout << "int=" << i << "\n"; } 

int main() 
{ 
    print(2 << 7); 
} 

Phương pháp đơn giản nhất để có được các bit của một giá trị là sử dụng một std::bitset<N> với N là các chữ số của các loại unsigned tương ứng, ví dụ:

char c('a'); 
std::bitset<std::numeric_limits<unsigned char>::digits> bits(c); 

Nếu bạn muốn nhận được bit bản thân bạn muốn che giấu các bit sử dụng unsigned đối tác của của các loại nguyên, ví dụ:

template <typename T> 
void get_bits(T val) 
{ 
    typedef typename std::make_unsigned<T>::type U; 
    U value(val); 
    for (std::size_t s(std::numeric_limits<U>::digits); s-- != 0;) { 
     std::cout << bool(value & (1u << s)); 
    } 
    std::cout << '\n'; 
} 
Các vấn đề liên quan