c++ - 有没有一种正统的方法来避免编译器警告 C4309 - "truncation of constant value"与二进制文件输出?

标签 c++ file-io compiler-warnings binary-data truncation

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

该程序运行良好。它同时使用 std::stringstream::put()std::ofstream::put()以两位十六进制整数作为参数。但是我得到编译器警告 C4309: "truncation of constant value"(in VC++ 2010) 每当参数到 put()大于 0x7f。显然编译器期待 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

最佳答案

我找到了令我满意的解决方案。它比将每个常量显式转换为 unsigned char 更优雅。这就是我所拥有的:

ss.put( 0xa4 ); // C4309

我认为“截断”是在将 unsigned char 隐式转换为 char 时发生的,但 Cong Xu 指出整数常量被假定为有符号的,并且任何大于 0x7f 的 1 从 char 提升为 int。然后如果传递给 put(),它实际上必须被截断(减少到一个字节)。通过使用后缀“u”,我可以指定一个无符号整数常量,如果它不大于 0xff,它将是一个 unsigned char。这就是我现在所拥有的,没有编译器警告:

ss.put( 0xa4u );

关于c++ - 有没有一种正统的方法来避免编译器警告 C4309 - "truncation of constant value"与二进制文件输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15467837/

相关文章:

java - 如何正确处理来自 close() 的 IOException

file - 最大文件大小 - log4j FileAppender 支持

c++ - 将指向成员函数的指针转换为指向静态函数的指针

c++ - QTableWidget,居中cellWidgets

java - 即使文件存在 FileNotFoundException

c - 在 GCC 中编译时使用 `-Wextra` 标志的缺点

c++ - GCC: "__unused__"与变量属性中的 "unused"

c - "initialization makes integer from pointer without a cast"数组初始化中逐渐减弱

c++ - N3568 提案中排除升级锁的原因是什么

c++ - QT/QML c++ 程序在从 QML 访问 QList 时崩溃