2011-10-06 12 views
7

少なくとも初歩的なエラー検出で、C++のiostreamからの基数10(10進)表現の符号なし整数を読みたい。私の見解では、符号なし整数には符号がないので、マイナス記号がこの場合は明らかにエラーになります。しかし、gccが異なる意見である:符号なし整数を読み取るときに、負の数を解析エラーとして検出するにはどうすればよいですか?

#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; 
} 

は、符号付き整数かのように、私の最後の行のための

4294967292 

の出力を与えるには、-4読み、unsigned int型に変換されていました。

Appearently, the GCC people see this as a feature。この動作を強制する標準がありますか?それを抜け出すためにパーサーを作成する方法がありません。つまり、変換エラーとして「-4」(おそらくは「-0」)を検出しますか?

+0

あなたは正しいバグレポートを投稿しましたか?それは抵抗なしで「固定」とマークされています。 – spraff

+0

@spraff:これはそうです、これは負の数の動作について言及しています。 – thiton

答えて

4

コンサルティングC++ 03,22.2.2.1.2/11の形式は、scanfと友人から継承され、変換された文字列は、署名されていない出力のものであっても、 。 strtoulは同じです。

したがって、動作がC++ 03の場合はC89、C++の場合はC99、C++の場合はC99であることが必要です。

-は最初の文字としてしか使用できないため、回避方法はであることを確認してからoperator>>を使用することです。

-1

これを行うと本当に違いはありますか?

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

これは、基礎となるCのルールはどのような場合でのサイレント変換ができるようになりますので、operator>>が符号の不一致を許容することをあまり重要ではありません。入力オペレータを「強化」することで、基本的に安全性を追加するわけではありません。

つまり、私の gcc(Solarisの4.3.5)は、変換エラーです。

+2

-Wconversion -Wsign-conversion -Werrorを指定してコンパイルすると、実際とは異なることになります。サイレントコンバージョンをオフにすることはできますが、iostreamのサイン処理は壊れません。 – thiton

+0

これはおそらく、リテラルの扱いと同じ方法で扱うことにしましたが、私は標準がそれについて何を言っているのか分かりません。 –

+0

変換エラーは良いことですが、古いgccバージョン(バグによると4.4.1より前)を使用していて、gccの人々が何かを修正しようとしたのかと疑問に思っているようです。 – thiton

0

私は5正しく22.2.2.1.2 /テーブルを読み込む場合は、符号なしに抽出するが負行うもに表示される%uscanfと同等であることを示している - >正変換を。

関連する問題