2009-04-08 20 views
7

Nếu tôi thực hiện đoạn mã sau trong C:C integer overflow hành vi khi giao đến số nguyên chiều rộng lớn hơn

#include <stdint.h> 

uint16_t a = 4000; 
uint16_t b = 8000; 

int32_t c = a - b; 

printf("%d", c); 

It in một cách chính xác '-4000' như kết quả. Tuy nhiên, tôi là một chút bối rối: không nên có một tràn số học khi trừ một số nguyên lớn hơn unsigned từ khác? Những quy tắc đúc nào được chơi ở đây? Câu hỏi này có vẻ hơi noobish, vì vậy bất kỳ tài liệu tham khảo sẽ được đánh giá rất nhiều.

Trả lời

5

Sự cố thực sự hơi phức tạp. Các toán tử của các biểu thức số học được chuyển đổi bằng các quy tắc cụ thể mà bạn có thể thấy trong Phần 3.2.1.5 của Standard (C89). Trong trường hợp của bạn, câu trả lời phụ thuộc vào loại uint16_t là gì. Nếu nó nhỏ hơn int, giả sử short int, thì toán hạng sẽ được chuyển đổi thành int và bạn nhận được -4000, nhưng trên hệ thống 16 bit, uint16_t có thể là unsigned int và chuyển đổi sang loại đã ký sẽ không tự động xảy ra.

+0

Tham chiếu của tôi đương nhiên là tiêu chuẩn cũ. Xem phản ứng của tgamblin cho C99. Mặc dù họ nói cùng một điều. – TrayMan

+0

3.2.1.5 là cho các chuyển đổi kép/float/int/etc. Anh ấy đang tìm kiếm các chương trình khuyến mãi không thể thiếu (dài/int/char/ngắn/etc) trong phiên bản 3.2.1.1 của tiêu chuẩn đó. Đó là trong 6.3.1.1 trong tiêu chuẩn mới hơn mà tôi đã liên kết ở trên. – tgamblin

+0

Ông cũng có thể muốn 3.2.1.2 quá (ints ký/unsigned) – tgamblin

1

Cả hai toán hạng được thăng cấp thành int32_t trong quá trình trừ. Nếu kết quả đã lớn hơn giá trị tối đa cho int32_t, bạn sẽ thấy tràn.

3

Câu trả lời ngắn gọn là tất cả đều được thăng cấp thành int trong khi trừ. Đối với câu trả lời dài, hãy xem phần 6.3.1.1 của C standard, tại đây nó nói về khuyến mãi số nguyên trong biểu thức số học. ngôn ngữ có liên quan từ các tiêu chuẩn:

Nếu một int thể đại diện cho tất cả các giá trị của loại gốc, giá trị là chuyển đổi thành một int; nếu không, nó là được chuyển đổi thành một số unsigned int. Các số này được gọi là các quảng cáo số số. Tất cả các loại khác không thay đổi theo các quảng cáo số .

Chi tiết cũng có trong đó, nhưng chúng trở nên khá khó chịu.

0

Có, trên thực tế, một tràn nhưng C không cho bạn biết.

Luồng tràn để lại giá trị xảy ra là -4000 khi được hiểu là số nguyên đã ký. Điều này hoạt động như được thiết kế trên các máy bổ sung của 2.

Cố gắng diễn giải kết quả là chưa ký, và bạn sẽ nhận thấy rằng (u1-u2) đánh giá một số dường như không liên quan khi u1 < u2.

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