Khi tiêu đề câu hỏi đọc, gán 2^31 cho biến số nguyên 32 bit đã ký và chưa ký cho kết quả không mong muốn.Kết quả lạ sau khi gán 2^31 cho biến số nguyên 32 bit đã ký và chưa ký
Dưới đây là chương trình ngắn (trong C++
), mà tôi thực hiện để xem những gì đang xảy ra:
#include <cstdio>
using namespace std;
int main()
{
unsigned long long n = 1<<31;
long long n2 = 1<<31; // this works as expected
printf("%llu\n",n);
printf("%lld\n",n2);
printf("size of ULL: %d, size of LL: %d\n", sizeof(unsigned long long), sizeof(long long));
return 0;
}
Dưới đây là kết quả:
MyPC/# c++ test.cpp -o test
MyPC/# ./test
18446744071562067968 <- Should be 2^31 right?
-2147483648 <- This is correct (-2^31 because of the sign bit)
size of ULL: 8, size of LL: 8
sau đó tôi thêm một chức năng p()
, để nó :
void p()
{
unsigned long long n = 1<<32; // since n is 8 bytes, this should be legal for any integer from 32 to 63
printf("%llu\n",n);
}
Khi biên dịch và chạy, đây là điều gây nhầm lẫn d tôi thậm chí nhiều hơn:
MyPC/# c++ test.cpp -o test
test.cpp: In function ‘void p()’:
test.cpp:6:28: warning: left shift count >= width of type [enabled by default]
MyPC/# ./test
0
MyPC/
Tại sao trình biên dịch phàn nàn về số lần dịch chuyển trái quá lớn? sizeof(unsigned long long
) trả về 8, vậy điều đó có nghĩa là 2^63-1 là giá trị tối đa cho loại dữ liệu đó không?
Nó đánh tôi rằng có lẽ n * 2 và n < < 1, không phải lúc nào cư xử theo cách tương tự, vì vậy tôi cố gắng này:
void s()
{
unsigned long long n = 1;
for(int a=0;a<63;a++) n = n*2;
printf("%llu\n",n);
}
này cung cấp cho các giá trị chính xác của 2^63 như đầu ra là 9223372036854775808
(Tôi đã xác minh nó bằng python). Nhưng những gì là sai trái khi làm một shit trái?
Một sự thay đổi số học trái của n là tương đương với nhân với 2 n (với điều kiện giá trị không tràn)
- Wikipedia
Giá trị không được tràn , chỉ một dấu trừ sẽ xuất hiện vì giá trị là 2^63 (tất cả các bit được đặt).
Tôi vẫn không thể tìm ra những gì đang xảy ra với sự dịch chuyển trái, bất kỳ ai cũng có thể giải thích điều này không?
PS: Chương trình này được chạy trên một bạc hà 32-bit hệ thống chạy Linux (nếu điều đó giúp)
này nên được 'unsigned dài dài n = 1ULL << 31;' – kirilloid
thần! nó có dễ dàng không ?! Tại sao tôi không nghĩ về nó. anyways, có 1ULL << 31 không hoạt động. cảm ơn! – Rushil