16

我的程序执行将二进制数据写入文件的常见任务,符合某种非文本文件格式。由于我正在写入的数据尚未存在于现有块中,而是在运行时逐字节放在一起,因此我使用std::ostream::put()而不是write(). 我认为这是正常程序。

该程序运行良好。它同时使用std::stringstream::put()std::ofstream::put()使用两位十六进制整数作为参数。但是每当参数put()大于 0x7f 时,我都会收到编译器警告 C4309:“常量值截断”(在 VC++ 2010 中)。显然编译器期望 a signed char,并且常量超出范围。但我认为实际上并没有发生任何截断。字节就像它应该的那样被写入。

编译器警告让我觉得我没有以正常的、可接受的方式做事。我描述的情况必须是常见的。有没有避免这种编译器警告的常用方法?或者这是一个应该忽略的毫无意义的编译器警告的例子?

我想了两种不优雅的方法来避免它。我可以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 charchar,但丛旭指出,整数常量被假定为有符号,任何大于 0x7f 的都被提升为charto int。如果传递给put(). 通过使用后缀“u”,我可以指定一个无符号整数常量,如果它不大于 0xff,它将是一个unsigned char. 这就是我现在所拥有的,没有编译器警告:

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

正如您猜到的那样,问题在于ostream.put()期望 a char,但0x7F它是 的最大值char,并且任何更大的值都会被提升为int。您应该转换为unsigned char,它的宽度应尽可能安全地char存储任何内容char,但也要使截断警告合法:

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