2014-09-12 19 views
8

Tôi có một số mã rất đơn giản:như thế nào dấu chấm động tràn xử lý iostreams

#include <iostream> 
#include <sstream> 
using namespace std; 

int main() 
{ 
    stringstream is("1.0 2.0 1e-500 1e500 12.0"); 
    double d = {17.0, 17.0, 17.0, 17.0, 17.0}; 

    for (int i=0; i < 5; ++i) 
    { 
    if (is >> d[i]) 
    { 
     cout<<"Conversion succeeded"<<endl; 
    } 
    else 
    { 
     cout<<"Conversion failed"<<endl; 
     is.clear(); 
    } 
    } 
    for (int i=0; i < 5; ++i) cout<<d[i]<<endl; 
} 

Khi tôi biên dịch mã này với g ++ 4.1.2 và chạy nó trên Redhat 5.10 (cùng biên dịch), tôi nhận được đầu ra :

Conversion succeeded 
Conversion succeeded 
Conversion failed 
Conversion failed 
Conversion succeeded 
1 
2 
0 
17 
17 
12 

Khi tôi thực hiện nhị phân cùng trên Redhat Linux 6.5 (trình biên dịch 4.4.7), tôi nhận được

Conversion succeeded 
Conversion succeeded 
Conversion succeeded 
Conversion failed 
Conversion succeeded 
1 
2 
0 
1.79769e+308 
12 

e là gì hành vi xpected? Đáy là succeeeding trên 4.4.7 nhưng thất bại trên 4.1.2. Lỗi tràn (nhưng vẫn thay đổi giá trị) trên 4.4.7 và không thành công mà không thay đổi bất kỳ thứ gì trên 4.1.2.

Hành vi không xác định hoặc chỉ đơn giản là không chính xác trên một hay khác?

+0

Câu hỏi hay. '>>' là gián tiếp (thông qua 'num_get') được định nghĩa theo các quy tắc của' strtold', và đối với cái thứ hai, rõ ràng là không xác định liệu dòng dưới được coi là một điều kiện lỗi hay không. Tuy nhiên, underflow là * not * được coi là một trong các điều kiện lỗi cho 'num_get'. Tôi không chắc chắn điều đó có nghĩa là nó không xác định, hoặc được xác định là trả về 0 thành công. – hvd

Trả lời

3

Theo C++ 11 22.4.2.1.2, việc chuyển đổi sẽ thất bại đối với tràn, nhưng không bị tràn. Trong trường hợp tràn, nó vẫn nên cung cấp một giá trị của giá trị đại diện lớn nhất cũng như thiết lập failbit.

Trình biên dịch gần đây của bạn có hành vi hiện đại chính xác.

Tuy nhiên, cả hai trình biên dịch cổ của bạn đều có trước C++ 11 trong nhiều năm. Trong các tiêu chuẩn trước đó, chuyển đổi được chỉ định để đưa ra lỗi nếu scanf sẽ; và không đưa ra giá trị trong trường hợp lỗi. Chuyển sang tiêu chuẩn C, scanf sẽ chuyển sang số strtod, do đó xác định lỗi trên tràn; nhưng liệu có lỗi trên phần dưới được thực thi hay không.

Trình biên dịch cũ hơn của bạn phù hợp với hành vi lịch sử.

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