2013-03-18 36 views
15

私のプログラムは、バイナリデータをファイルに書き込んで、特定の非テキストファイル形式に準拠させるという共通の作業を行います。私が書いているデータはすでに存在するチャンクにはないので、実行時にバイト単位でまとめられているので、write()の代わりにstd::ostream::put()を使用します。私はこれが通常の手順であると仮定します。バイナリファイル出力でコンパイラの警告C4309 - "定数値の切り捨て"を避けるための正統な方法はありますか?

プログラムは正常に動作します。これは、引数として2桁の16進数を持つstd::stringstream::put()std::ofstream::put()の両方を使用します。しかし、コンパイラの警告C4309:put()への引数が0x7fより大きいときはいつでも(VC++ 2010で)「一定値の切り捨て」が得られます。明らかにコンパイラはsigned charを期待しており、定数は範囲外です。しかし、私は切り捨てが実際に起こっているとは思わない。バイトは、それが想定されているように書かれます。

コンパイラの警告は私が普通の、受け入れられた方法で物事をやっていないと私に思います。私が説明した状況は、共通のものでなければなりません。 このようなコンパイラの警告を回避する一般的な方法はありますか?または、これは無視する必要がある無意味なコンパイラ警告の例ですか?

私はそれを避けるために2つの控えめな方法を考えました。すべての呼び出しでmystream.put(char(0xa4))のような構文を使用できます。またはstd::stringstreamの代わりにstd::basic_stringstream< unsigned char >を使用することができますが、そのトリックはstd::ofstreamで動作するとは思われません。テンプレートタイプではありません。 ofstreamはバイナリファイルの作成を目的としているため、ここではより良い解決策が必要なようです。

あなたの考えは?

--EDIT--

ああ、私はstd::ofstreamテンプレートタイプないことに関する間違っていました。実際にはstd::basic_ofstream<char>ですが、その方法を試してみましたが、定義されたメソッドがなく、多態性の非互換性がstd::ostreamではうまくいかないことに気付きました。

ここでのサンプルコードです:

stringstream ss; 
int a, b; 
/* Do stuff */ 
ss.put(0); 
ss.put(0x90 | a); // oddly, no warning here... 
ss.put(b);  // ...or here 
ss.put(0xa4);  // C4309 
+4

具体的なコード例をあなたの質問に追加できますか? –

+1

私は、コンパイラライターが "無意味な"警告を生成する時間を持っていないと確信しています。 –

答えて

17

私はと満足している解決策を見つけました。すべての定数を明示的にキャストするよりもエレガントです。unsigned charです。これは私が持っていたものです:

ss.put(0xa4); // C4309 

私は「切り捨て」charunsigned charをキャスト暗黙的で起こっていたと思ったが、コング徐は整数定数が署名されると仮定されていることを指摘し、0x7fのが取得するよりも、いずれか大きいですcharからintに昇格しました。 put()に渡された場合、実際には切り捨てられます(1バイトに切り捨てられます)。接尾辞 "u"を使用することで、符号なし整数定数を指定できます。0xffより大きい場合はunsigned charになります。コンパイラの警告なしでこれが私の今のものです:

ss.put(0xa4u); 
7
std::stringstream ss; 
ss.put(0x7f); 
ss.put(0x80); //C4309 

あなたが推測してきたように、問題はostream.put()charを期待していることですが、0x7Fcharの最大値であり、そしてより大きなものがintに昇格ます。あなたは同じ広charように、それは安全に行い、char何かを保存するだけでなく、切り捨ての警告が正当なものにするだろうしている、unsigned charにキャストする必要があります

ss.put(static_cast<unsigned char>(0x80)); // OK 
ss.put(static_cast<unsigned char>(0xFFFF)); //C4309 
+1

なぜ 'ss.put(unsigned char(0x80))'や 'ss.put(unsigned char)0x80)'の代わりに 'ss.put(static_cast (0x80));を使用しますか?何らかの理由で静的なキャストが優先されていますか? –

+1

@SamKauffman、これは単なるキャストを行う現代のC++の方法です。より洗練されていますが、あまりあいまいでなく安全です。 –

+0

@CongXu、ありがとう!あなたがプロモーションについて書いたことは、私が切り捨てが実際に起こっていることを理解するのを助けました。 –

関連する問題