2011-11-24 30 views
5

Đoạn mã sau xuất ra 0,1,32,33. Mà là truy cập trực quan để nói rằng ít nhất. Nhưng nếu tôi thay thế chữ 1 bằng loại hằng số được kết hợp "ONE", vòng lặp sẽ chạy tốt.Lỗi trình biên dịch bit dịch chuyển hoặc trường hợp góc?

Điều này là với gcc 4.6.2 và -std = C++ 0x.

#include<iostream> 
#include<cstdint> 
using namespace std; 
int main() 
    { 
    int64_t bitmask = 3; 
    int64_t k; 
    const int64_t ONE = 1; 
    cout<<"bitmask = "<<bitmask<<endl; 

    for(k=0; k<64; k++) 
     { 
     if(bitmask & (1<<k)) 
      { 
      cout<<"k="<<k<<endl; 
      } 
     } 

    return 0; 
    } 

EDIT Câu hỏi: Như Ben chỉ ra, 1 được xem là rộng 32 bit theo mặc định. Tại sao nó không được phát triển đến 64 bit khi nó là hợp tác và là 64 bit.

SOLUTION

số < < không yêu cầu mỗi bên có cùng loại. Sau khi tất cả, tại sao làm cho phía bên phải một int64_t khi sự thay đổi tối đa có sẵn phù hợp trong một char? Chương trình khuyến mãi chỉ xảy ra khi bạn giao dịch với các toán tử số học, không phải tất cả các toán tử.

sao chép từ ý kiến ​​của Bill dưới đây

+1

bản sao có thể có của [Làm thế nào để tôi dịch chuyển bit dài hơn 32 bit?] (Http://stackoverflow.com/questions/2404439/how-do-i-bit-shift-a-long-by- nhiều hơn 32 bit) –

Trả lời

7

Đây là một vấn đề: (1<<k).

1 là một chữ không thể thiếu phù hợp với một số int.

Nếu int có ít hơn 64 bit trên nền tảng của bạn, thì (1<<k) sẽ có hành vi không xác định vào cuối vòng lặp, khi k lớn. Trong trường hợp của bạn, trình biên dịch đang sử dụng hướng dẫn bithift của Intel và hành vi không xác định được đưa ra theo cách mà Intel định nghĩa các thay đổi lớn hơn kích thước toán hạng - các bit cao bị bỏ qua.

Bạn có thể muốn (1LL<<k)


gì tiêu chuẩn nói (phần 5,8 expr.shift):

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á. Hành vi này là không xác định nếu toán hạng bên phải là âm hoặc lớn hơn hoặc bằng độ dài tính bằng bit của toán hạng bên trái được quảng bá.

Điều này trái ngược với từ ngữ "Chuyển đổi số học thông thường được thực hiện cho toán hạng kiểu số học hoặc đếm." hiện diện cho ví dụ: toán tử cộng và trừ.

Ngôn ngữ này không thay đổi giữa C++ 03 và C++ 11.

+0

Nhưng không nên 1 được thăng cấp thành int64_t vì hợp tác của nó là 64 bit. Nếu bạn cố gắng thêm một int và một float, nó chắc chắn sẽ thúc đẩy int nổi. – rpg

+0

@rpg: Không. '<<' không yêu cầu mỗi bên có cùng loại. Sau khi tất cả, tại sao làm cho bên phải một 'int64_t' khi sự thay đổi tối đa có sẵn phù hợp trong một' char'? Chương trình khuyến mãi chỉ xảy ra khi bạn giao dịch với các toán tử số học, không phải tất cả các toán tử. –

+0

@rpg: Không.Các toán hạng có các hàm khác nhau (một là một giá trị, hàm kia là một số bit). Nó sẽ không có ý nghĩa để ép buộc cả hai toán hạng cùng loại. Và trên thực tế, các cuộc gọi chuẩn cho toán hạng bên trái được quảng bá độc lập với loại toán hạng bên phải. –

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