2015-12-16 16 views
5

Tôi đã cố gắng tập thể dục KR 2.1 - xác định phạm vi của long biến bằng cách tính toán trực tiếp.Khi dịch chuyển trái không giống như nhân với 2

#include <stdio.h> 
#include <limits.h> 

int main() 
{ 
    unsigned short long_bits = sizeof(long) * CHAR_BIT; 
    printf("LONG_MAX = %ld\n", (1L << (long_bits - 1)) - 1); 
    printf("LONG_MIN = %ld\n", (-1) * (1L << (long_bits - 1))); 
    printf("ULONG_MAX (1) = %lu\n", (1UL << long_bits) - 1); // doesn't work 

    printf("ULONG_MAX (2) = %lu\n", 2*(1UL << (long_bits - 1)) - 1); // work 
    printf("\n"); 
} 
  • ULONG_MAX (1) = 0 là sai bởi vì sự thay đổi tràn trái Tôi cho rằng.
  • ULONG_MAX (2) = 18446744073709551615 dường như đúng bằng cách thay thế sự thay đổi cuối cùng bên trái với một nhân với 2.

Vì vậy, có vẻ như nhà điều hành dịch trái bị tràn, nhưng nhân không? Tính toán trung gian này có 2*(1UL << (long_bits - 1))quảng cáo cho một số loại hơn long không? Trong máy của tôi, longlong long hoàn toàn giống nhau (8 byte).


Edit: Như Lundin chỉ ra, tất cả cần thiết cho ULONG_MAXprintf("ULONG_MAX = %lu\n", ~0L);

Sử dụng dịch trái trong trường hợp này gây ra UB, và nhân với 2 là khả năng UB, quá (mặc dù kết quả của trường hợp 2 hình chính xác).

+4

Theo quy tắc chung: số học đã ký bị bị tràn (tiềm năng); unsigned số học * không thể * tràn (kể từ khi thực hiện modulo 2^N). – Jens

+0

Trường hợp 2 không đúng ... do tràn như trường hợp 1 – LPs

+0

@LPs - đầu ra của trường hợp 2 có vẻ đúng mặc dù. Đó là câu hỏi của tôi, tràn dường như không xảy ra trong trường hợp này – artm

Trả lời

4

Hành vi dịch chuyển trái giá trị chỉ được xác định nếu số tiền bạn dịch chuyển trái nhỏ hơn kích thước của loại. Do đó, 1UL << long_bits là hành vi không xác định và bất cứ điều gì có thể xảy ra, bao gồm cả dæmons bay ra khỏi mũi của bạn.

Cho phép n là số bit trong loại chúng tôi đang làm việc. Trong thực tế, tùy thuộc vào nền tảng, có hai hành vi xảy ra trong trường hợp này: Hoặc bất kỳ sự dịch chuyển trái nào theo n hoặc nhiều hơn sẽ tạo ra 0 (khi toàn bộ mẫu bit bị dịch chuyển) hoặc dịch chuyển trái được giảm modulo n , do đó, dịch chuyển trái của n địa điểm hoạt động như một sự dịch chuyển trái bởi 0 địa điểm, có lãi 1UL << 0 hoặc 1.

+0

Cảm ơn. Tôi đồng ý trường hợp 1 là không xác định. Trường hợp 2 có đúng không? '2 * (1UL << (long_bits - 1))' xuất hiện nhiều hơn loại 'long' có thể giữ, vì vậy tôi tự hỏi tại sao nó hoạt động ở đây – artm

+1

@artm Trường hợp đó cũng không xác định. Tại sao bạn không làm '(unsigned long) -1L'? – fuz

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