2011-02-09 26 views
53

Chính xác điều gì xảy ra ở đây?Dịch chuyển trái với số chuyển đổi âm

a << -5

Rõ ràng là nó không đúng sự thay đổi. Nhưng cuốn sách tôi đọc tiểu bang:

Trên một máy, biểu hiện này thực sự thực hiện một sự thay đổi trái của 27 bit

Câu hỏi của tôi là; tại sao? Điều gì gây ra một sự thay đổi trái của 27 bit? Và chính xác điều gì sẽ xảy ra khi chuyển dịch với số lần dịch chuyển âm? Cảm ơn bạn.

Trả lời

63

Số nguyên âm ở bên tay phải là hành vi không xác định bằng ngôn ngữ C.

ISO 9899: 1999 6.5.7 khai thác thay đổi Bit-khôn ngoan §3

Các chương trình khuyến mãi được thực hiện nguyên trên mỗi toán hạng. Loại kết quả là của toán hạng bên trái được quảng bá . Nếu giá trị của toán hạng bên phải là âm hoặc là lớn hơn hoặc bằng với chiều rộng của các toán hạng trái bạt, hành vi là undefined.

+23

Btw nếu sách của bạn không đề cập rằng đây là hành vi không xác định, bạn nên cân nhắc việc mua một cuốn sách khác. – Lundin

+1

Tùy thuộc vào những gì khác của cuốn sách nói, bạn có thể tranh luận này là chính xác những gì nó đã nói (mặc dù nó có thể đứng được rõ ràng hơn). "Trên một máy, một cái gì đó xảy ra" ngầm có nghĩa là nó có thể không xảy ra với người khác. – 3Doubloons

+0

Nếu điều này không làm việc, nó sẽ là một số hoạt động mà sẽ có hành vi tương đương với hành vi mong muốn trong câu hỏi? Có vẻ như buồn khi viết một phương trình cho hoạt động cụ thể này: (Tôi cố gắng thực hiện một ca làm đúng để làm cho 1 là 0. – patrik

11

Hành vi không xác định.

Trong số học nhị phân 5 bit, hai bổ sung -5 có cùng biểu diễn nhị phân như dấu +27, có thể giải thích rằng nền tảng cụ thể đó.

+0

là số học nhị phân 5 bit là một thực tế? Làm thế nào char sẽ được xác định? – CIsForCookies

+2

@ClsForCookies - ở cấp độ điện, đó là một điều thực sự. Không có gì đặc biệt về 8. –

1

Nếu giá trị bạn đang dịch chuyển là biến 32 bit, dịch chuyển -5 sẽ chuyển thành "vòng lặp" và chuyển 27 tiến. Dịch chuyển chỉ có thể diễn ra theo kiểu "không dấu".

+0

Nhưng nếu biến 32 bit được ký, các chương trình khuyến mãi số nguyên sẽ không thay đổi độ ký kết của -5. Và sau đó hành vi là không xác định và chương trình là miễn phí để ngăn chặn và bắt lửa. – Lundin

+0

có thể. Dù sao tôi nghĩ rằng đó là một thực tế xấu :) – arnorhs

16

Như đã được trả lời bởi các thành viên khác, nó tạo ra hành vi không xác định. Những gì tôi muốn đề cập ở đây là bạn trích dẫn từ cuốn sách ("Trên một máy") có vẻ là một phần. Nó không nói chung hành vi. Cuốn sách cũng có thể giải thích rằng hành vi không được xác định theo tiêu chuẩn. BTW, tôi chỉ đi qua "The New C Tiêu chuẩn - Một kinh tế và bình luận văn hóa" và phát hiện tuyên bố này:

Intel Pentium SAL hướng dẫn (tạo ra bởi cả hai gcc và Microsoft C++ để đánh giá trái thay đổi) chỉ sử dụng ngũ bit dưới cùng của sự thay đổi lượng

này rất tốt giải thích tại sao một sự thay đổi trái -5 có thể dẫn vào một sự thay đổi trái 27 (đối với đại diện bổ sung 2 của số âm)

+3

Tôi chắc chắn rằng câu "Trên một máy" trong cuốn sách của OP chỉ phục vụ như là một ví dụ, ngay sau khi nói rằng điều này là không xác định. Nó thực sự là một trong những ví dụ tốt đẹp mà "không xác định" thực sự có nghĩa là bất cứ điều gì, và không chỉ "sạch" chấm dứt đột ngột của chương trình thực hiện.Nếu được sử dụng theo cách này, sẽ không có ý nghĩa gì nếu ấn tượng rằng sự dịch chuyển trái của 27 là điều mà bạn có quyền mong đợi. –

+0

+1 để trả lời một phần câu hỏi "chính xác những gì xảy ra [trên" một máy "được trích dẫn] khi dịch chuyển với số lần dịch âm". chắc chắn, UB là UB, và vì vậy chúng tôi không nên giả định bất cứ điều gì về nó, nhưng lời giải thích này là cực kỳ minh họa của các loại nguy hiểm đã dẫn họ đến _make_ nó UB. (bộ não của tôi luôn muốn nói 'nhưng tại sao nó không thể được định nghĩa cho các số nguyên theo nghĩa đen', nhưng sau đó tôi nghĩ nhiều hơn và nhận ra điều đó là vô lý ;-) –

0
int main() 
{ 
    unsigned int a = 1; 
    printf("%u\n",a<<(-1)); 
    return 0; 
} 

Đầu ra là 2147483648.

Dưới đây là giả định và xác nhận của tôi: (! Chỉ giả định)

1.Toán hạng "< <" phải là loại int chưa được ký,

trước tiên, (int) “-1” sẽ được nhập vào (unsigned int) "-1". Nguyên nhân loại int là biểu diễn hai bổ sung, kết quả sẽ là 2^32-1 (unsigned int)

2.Do đến số 2^32-1 lớn hơn số chuyển tối đa, 2^32 - 1 sẽ được mod 32, bằng với 27

tôi cũng cố gắng một số con số toán hạng phải nagetive khác, và kết quả tính toán thủ công với quy tắc assumpted sẽ giống với những gì sản phẩm của IDE của tôi.

Tôi đang cố gắng tìm một số tài liệu chính thức hỗ trợ, phù thủy có thể xác minh cho dù giả định của tôi là đúng hay không. Có lẽ bạn có thể cho tôi biết.

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