2012-01-03 81 views
7

Tôi nhận được kết quả từ sự dịch chuyển trái mà tôi không thể tìm thấy lời giải thích.Tại sao kết quả của unsigned char << unsigned char không phải là unsigned char

unsigned char value = 0xff; // 1111 1111 
unsigned char = 0x01; // 0000 0001 

std::cout << "SIZEOF value " << sizeof(value) << "\n"; // prints 1 as expected 
std::cout << "SIZEOF shift " << sizeof(shift) << "\n"; // prints 1 as expected 

std::cout << "result " << (value << shift) << "\n"; // prints 510 ??? 

std::cout << "SIZEOF result " << sizeof(value << shift) << "\n"; // prints 4 ??? 

Tôi đã chờ đợi kết quả được 1111 1110 nhưng thay vào đó tôi nhận được int (?) Với giá trị của 1 1111 1110.

Làm thế nào các bit của một ký tự chưa ký được chuyển sang trái để các bit bị cắt ngắn và kết quả là 1111 1110?

Điều tôi đang cố gắng làm là đọc chuỗi byte và diễn giải chúng dưới dạng số nguyên có độ dài khác nhau (1-32 bit).

F0  F5 
1111 0000 1111 0101 

có thể

0F (first 4 bits) 
0F (next 8 bits) 
05 (last 4 bits) 

Có một cái gì đó này để làm với thực tế rằng số học không được thực hiện với các loại nhỏ hơn int?

+0

11111111 << 1 là trên thực tế 111111110, bạn đang in kết quả của biểu thức, hãy thử làm: 'value = value << shift;' và sau đó 'cout << value;' – Yaniro

Trả lời

9

Trích dẫn một số dự thảo tiêu chuẩn 2011:

5,8 phím Shift toán tử [expr.shift]

...

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

4,5 Khuyến mãi Integral [conv.prom]

Một prvalue của một kiểu số nguyên khác hơn bool, char16_t, char32_t, hoặc wchar_t có số nguyên chuyển đổi rank (4.13) là ít hơn xếp hạng của int có thể được chuyển đổi thành giá trị pr của kiểu int nếu int có thể biểu thị tất cả các giá trị của loại nguồn là ; nếu không, prvalue nguồn có thể được chuyển đổi sang một prvalue kiểu unsigned int

...

Vì vậy, value được thăng int, và loại value << shift là kiểu của toán hạng bên trái thăng chức , tức là int.

Bạn có thể đạt được kết quả mong muốn của bạn một trong các cách sau:

std::cout << "result " << ((unsigned char)(value << shift)) << "\n"; 
std::cout << "result " << ((value << shift)&0xff) << "\n"; 
2

Chỉ cần quăng nó trở lại một char unsigned:

std::cout << "result " << static_cast<unsigned char>(value << shift) << "\n"; 

Hoặc, sử dụng Bitwise-AND:

std::cout << "result " << ((value << shift) & 0xFF) << "\n"; 
2

Bạn có thể che giấu các bit bạn quan tâm:

(value << shift) & 0xff 

gì bạn đang nhìn thấy là kết quả của chương trình khuyến mãi số nguyên và là một phần của ngôn ngữ. Hãy tưởng tượng bạn đang soạn một số nguyên 16 bit từ 2 số nguyên 8 bit - bạn sẽ không muốn quảng cáo theo cách thủ công đến số nguyên chiều rộng cao hơn để nhận các bit cao và thấp vào đúng vị trí, đúng không?

Các vấn đề liên quan