Câu hỏi này lần đầu tiên được lấy cảm hứng từ (bất ngờ) kết quả của mã này:c tiêu chuẩn và bitshifts
uint16_t t16 = 0;
uint8_t t8 = 0x80;
uint8_t t8_res;
t16 = (t8 << 1);
t8_res = (t8 << 1);
printf("t16: %x\n", t16); // Expect 0, get 0x100
printf(" t8: %x\n", t8_res); // Expect 0, get 0
Nhưng nó quay ra này có ý nghĩa:
6.5.7 Bitwise nhà khai thác dịch chuyển
chế
Mỗi phòng trong số toán hạng phải có số nguyên kiểu
Như vậy dòng ban đầu bối rối tương đương với:
t16 = (uint16_t) (((int) t8) << 1);
Một chút IMHO phi trực quan, nhưng ít nhất cũng xác định.
Ok, tuyệt vời, nhưng sau đó chúng tôi làm:
{
uint64_t t64 = 1;
t64 <<= 31;
printf("t64: %lx\n", t64); // Expect 0x80000000, get 0x80000000
t64 <<= 31;
printf("t64: %lx\n", t64); // Expect 0x0, get 0x4000000000000000
}
// chỉnh sửa: sau khi tranh luận nghĩa đen tương tự như trên, sau đây sẽ tương đương:
t64 = (uint64_t) (((int) t64) << 31);
// do đó sự nhầm lẫn của tôi/expectation [end_edit]
Bây giờ, chúng tôi nhận được kết quả trực quan, nhưng không phải những gì sẽ được bắt nguồn từ việc đọc (theo nghĩa đen) của tôi về tiêu chuẩn. Khi nào thì "xúc tiến loại tự động tiếp theo" này diễn ra như thế nào? Hoặc là có một giới hạn ở những nơi khác mà một loại không bao giờ có thể được giáng chức (mà sẽ có ý nghĩa?), Trong trường hợp đó, làm thế nào để các quy tắc khuyến mãi áp dụng cho:
uint32_t << uint64_t
Kể từ khi tiêu chuẩn không nói cả hai đối số được thăng chức int; cả hai đối số có nên được quảng cáo cùng loại ở đây không?
// chỉnh sửa:
Cụ thể hơn, những gì nên kết quả của:
uint32_t t32 = 1;
uint64_t t64_one = 1;
uint64_t t64_res;
t64_res = t32 << t64_one;
// end chỉnh sửa
Câu trả lời cho câu hỏi trên đã được giải quyết khi chúng ta nhận ra rằng spec không yêu cầu quảng bá cho int
cụ thể, thay vì một số integer type
, mà uint64_t đủ điều kiện là.
// CLARIFICATION EDIT:
Ok, nhưng bây giờ tôi lại bị nhầm lẫn. Cụ thể, nếu uint8_t
là một loại số nguyên thì tại sao nó được thăng cấp lên int
? Nó dường như không có liên quan đến hằng int 1, như tập thể dục sau minh họa:
{
uint16_t t16 = 0;
uint8_t t8 = 0x80;
uint8_t t8_one = 1;
uint8_t t8_res;
t16 = (t8 << t8_one);
t8_res = (t8 << t8_one);
printf("t16: %x\n", t16);
printf(" t8: %x\n", t8_res);
}
t16: 100
t8: 0
Tại sao (t8 < < t8_one) biểu hiện được phát huy nếu uint8_t là một kiểu số nguyên?
-
Để tham khảo, tôi đang làm việc từ ISO/IEC 9899: TC9, WG14/N1124 ngày 06 tháng 5, 2005. Nếu đó là lỗi thời và ai cũng có thể cung cấp một liên kết đến một bản sao gần đây , điều đó cũng được đánh giá cao.
Tôi hoàn toàn không hiểu tại sao bạn nói '// Mong đợi 0x0' sau lần dịch thứ hai bên trái 31 bit ... –
Tôi bối rối như Greg, nhưng sẽ mong đợi các loại sẽ không bao giờ tự động hạ cấp (thu hẹp), chỉ được quảng cáo (mở rộng). –
Khi đọc tiêu chuẩn, t64 = (uint64_t) (((int) t64) << 31) là một dòng tương đương, trong trường hợp đó bit thiết lập sẽ bị mất để cắt ngắn int. – Pat