2011-10-06 32 views
7

Tôi muốn đọc các số nguyên không dấu trong biểu diễn cơ sở 10 (thập phân) từ một iốt luồng C++ với ít nhất là phát hiện lỗi thô sơ. Theo quan điểm của tôi, các dấu trừ sẽ rõ ràng là một lỗi trong trường hợp này, bởi vì các số nguyên chưa ký không có dấu. Tuy nhiên, gcc là một ý kiến ​​khác nhau:Làm cách nào để phát hiện số âm khi phân tích lỗi khi đọc số nguyên không dấu?

#include <iostream> 
#include <sstream> 

int main() { 
    std::stringstream a("5"), b("-0"), c("-4"); 
    unsigned int i; 
    a >> i; if (a) std::cout << i << std::endl; else std::cout << "Conversion failure" << std::endl; 
    b >> i; if (b) std::cout << i << std::endl; else std::cout << "Conversion failure" << std::endl; 
    c >> i; if (c) std::cout << i << std::endl; else std::cout << "Conversion failure" << std::endl; 
    return 0; 
} 

mang lại cho tôi một đầu ra của

4294967292 

cho dòng cuối cùng, như thể một số nguyên ký -4 đã đọc và chuyển đổi sang int unsigned.

Appearently, the GCC people see this as a feature. Có một số tiêu chuẩn bắt buộc hành vi này và có cách nào ngắn viết một trình phân tích cú pháp riêng để thoát khỏi nó, tức là phát hiện "-4" (và có thể "-0") làm lỗi chuyển đổi không?

+0

Bạn đã đăng báo cáo lỗi đúng chưa? Đó là một đánh dấu "cố định" mà không có bất kỳ kháng chiến. – spraff

+0

@spraff: Có vẻ như vậy, điều này đề cập đến hành vi số âm. – thiton

Trả lời

4

Tư vấn C++ 03, 22.2.2.1.2/11, các định dạng được kế thừa từ scanf và bạn bè, từ đó tất cả đều nói rằng chuỗi ký tự được chuyển đổi là "tùy chọn được ký", ngay cả đối với những đầu ra chưa được ký . strtoul giống nhau.

Vì vậy, tôi giả sử bạn có thể nói tiêu chuẩn yêu cầu hành vi là C89 cho C++ 03, C99 cho C++ 11.

- xảy ra chỉ được phép làm ký tự đầu tiên, tôi cho rằng cách khắc phục là kiểm tra xem nó bằng peek trước khi sử dụng operator>>.

-1

Nó có thực sự khác nếu bạn làm điều này?

int i; 
unsigned int u; 
c >> i; 
u = i; 
std :: cout << u; 

Nó không quan trọng đến nỗi operator>> dung túng không phù hợp dấu vì các quy tắc cơ bản C sẽ cho phép chuyển đổi im lặng trong mọi trường hợp. Bạn về cơ bản không thêm bất kỳ sự an toàn nào bằng cách "tăng cường" toán tử đầu vào.

Điều đó nói rằng, tôi gcc (4.3.5 trên Solaris) cho biết đó là một lỗi chuyển đổi.

+2

Nó sẽ thực sự khác khi biên dịch với -Wconversion -Wsign-conversion -Werror. Tôi có thể tắt chuyển đổi im lặng nhưng không bị xử lý dấu iostream bị hỏng. – thiton

+0

Nó có thể quyết định xử lý nó theo cùng một cách literals được xử lý, nhưng tôi không biết những gì các tiêu chuẩn nói về nó. –

+0

Lỗi chuyển đổi là một điều tốt, và có vẻ là do bạn sử dụng phiên bản gcc cũ (trước 4.4.1, theo lỗi), khiến tôi vẫn tự hỏi tại sao gcc mọi người cố gắng sửa chữa bất kỳ thứ gì. – thiton

0

Nếu tôi đọc 22.2.2.1.2/table 5 một cách chính xác nó cho thấy rằng chiết xuất thành một unsigned tương đương với scanf với %u mà dường như cũng làm tiêu cực -> chuyển đổi tích cực.

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