16

私のプログラムは、特定の非テキストファイル形式に準拠して、バイナリデータをファイルに書き込むという一般的なタスクを実行します。私が書いているデータはまだ既存のチャンクにはなく、実行時にバイトごとにまとめられるため、std::ostream::put()の代わりにを使用しますwrite()。これは通常の手順だと思います。

プログラムは問題なく動作します。引数としてと2桁の16進整数の両方を使用std::stringstream::put()します。しかし、toの引数が0x7fより大きい場合はstd::ofstream::put()常に、コンパイラの警告C4309:「定数値の切り捨て」(VC ++ 2010の場合)が表示されます。put()明らかに、コンパイラはを期待してsigned charおり、定数は範囲外です。しかし、実際には切り捨てが行われているとは思いません。バイトは想定どおりに書き込まれます。

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

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

あなたの考え?

- 編集 -

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

2 に答える 2

18

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

ss.put( 0xa4 ); // C4309

unsigned charへの暗黙的なキャストで「切り捨て」が発生していると思いましたが、Cong Xu は、整数定数は符号付きであると見なされ、0x7f より大きいものは からにchar昇格されると指摘しました。に渡される場合は、実際に切り捨てられる (1 バイトに切り詰められる) 必要があります。接尾辞「u」を使用することで、符号なし整数定数を指定でき、それが 0xff 以下の場合は. これは、コンパイラの警告なしで、私が今持っているものです:charintput()unsigned char

ss.put( 0xa4u );
于 2013-03-18T20:49:25.520 に答える
7
std::stringstream ss;
ss.put(0x7f);
ss.put(0x80); //C4309

ご想像のとおり、問題は が をostream.put()期待していることですcharが、0x7Fは の最大値でcharあり、それより大きいものは に昇格しintます。にキャストする必要があります。これは、すべてを安全に保存するunsigned charのと同じくらい広いだけでなく、切り捨ての警告を正当なものにします。charchar

ss.put(static_cast<unsigned char>(0x80)); // OK
ss.put(static_cast<unsigned char>(0xFFFF)); //C4309
于 2013-03-18T00:30:13.507 に答える