2013-06-26 31 views
10

Xem xét một hàm giá trị tuyệt đối tiêu biểu (trong đó vì lợi ích của các đối số kiểu không thể thiếu trong kích thước tối đa là dài):Có cách nào an toàn để lấy giá trị tuyệt đối chưa ký của một số nguyên đã ký, mà không kích hoạt tràn không?

unsigned long abs(long input); 

Một thực hiện ngây thơ của điều này có thể giống như thế:

unsigned long abs(long input) 
{ 
    if (input >= 0) 
    { 
     // input is positive 
     // We know this is safe, because the maximum positive signed 
     // integer is always less than the maximum positive unsigned one 
     return static_cast<unsigned long>(input); 
    } 
    else 
    { 
     return static_cast<unsigned long>(-input); // ut oh... 
    } 
} 

này mã kích hoạt hành vi không xác định, bởi vì sự phủ định của input có thể tràn, và kích hoạt tràn số nguyên đã ký là hành vi không xác định. Ví dụ, trên máy bổ sung 2s, giá trị tuyệt đối của std::numeric_limits<long>::min() sẽ lớn hơn std::numeric_limits<long>::max().

Tác giả thư viện có thể làm gì để giải quyết vấn đề này?

Trả lời

16

Trước tiên, bạn có thể truyền sang biến chưa ký. Điều này cung cấp hành vi được xác định rõ. Nếu thay vào đó, mã trông giống như sau:

unsigned long abs(long input) 
{ 
    if (input >= 0) 
    { 
     // input is positive 
     return static_cast<unsigned long>(input); 
    } 
    else 
    { 
     return -static_cast<unsigned long>(input); // read on... 
    } 
} 

chúng tôi gọi hai hoạt động được xác định rõ. Chuyển đổi số nguyên ký hợp đồng với một unsigned cũng được xác định bởi N3485 4.7 [conv.integral]/2:

Nếu loại đích là unsigned, giá trị kết quả là số nguyên unsigned nhất đồng dư với số nguyên nguồn (modulo 2^n trong đó n là số bit được sử dụng để biểu diễn loại không dấu). [Lưu ý: Trong biểu diễn bổ sung của hai, chuyển đổi này là khái niệm và không có thay đổi trong mẫu bit (nếu không có cắt ngắn). - end note]

Điều này về cơ bản nói rằng khi thực hiện chuyển đổi cụ thể chuyển từ ký sang unsigned, người ta có thể giả định bao bọc kiểu unsigned.

Sự phủ nhận các số nguyên unsigned cũng được xác định bởi 5.3.1 [expr.unary.op]/8:

Các tiêu cực của một số lượng unsigned được tính bằng cách trừ đi giá trị của nó từ 2^n, trong đó n là số bit trong toán hạng được thăng hạng.

Hai yêu cầu này có hiệu lực buộc triển khai hoạt động như máy bổ sung 2 giây, ngay cả khi máy cơ bản là máy bổ sung 1 hoặc máy có độ lớn đã ký.

+1

Câu trả lời hay, mặc dù câu hỏi của riêng bạn, nhưng +1. – Bathsheba

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