简体   繁体   English

有没有一种正统的方法可以避免编译器警告C4309 - 使用二进制文件输出“截断常量值”?

[英]Is there an orthodox way to avoid compiler warning C4309 - “truncation of constant value” with binary file output?

My program does the common task of writing binary data to a file, conforming to a certain non-text file format. 我的程序执行将二进制数据写入文件的常见任务,符合某种非文本文件格式。 Since the data I'm writing is not already in existing chunks but instead is put together byte by byte at runtime, I use std::ostream::put() instead of write() . 由于我正在编写的数据不是已经在现有的块中,而是在运行时逐字节放在一起,我使用std::ostream::put()而不是write() I assume this is normal procedure. 我认为这是正常的程序。

The program works just fine. 该程序工作得很好。 It uses both std::stringstream::put() and std::ofstream::put() with two-digit hex integers as the arguments. 它使用带有两位十六进制整数的std::stringstream::put()std::ofstream::put()作为参数。 But I get compiler warning C4309: "truncation of constant value" (in VC++ 2010) whenever the argument to put() is greater than 0x7f. 但是每当put()的参数大于0x7f时,我都会收到编译器警告C4309:“截断常量值”(在VC ++ 2010中)。 Obviously the compiler is expecting a signed char , and the constant is out of range. 显然编译器期望有signed char ,并且常量超出范围。 But I don't think any truncation is actually happening; 但我认为任何截断都不会发生; the byte gets written just like it's supposed to. 字节的写入就像它应该的那样。

Compiler warnings make me think I'm not doing things in the normal, accepted way. 编译器警告让我觉得我没有以正常,可接受的方式做事。 The situation I described has to be a common one. 我描述的情况必须是一个普遍的情况。 Is there are common way to avoid such a compiler warning ? 是否有通用的方法来避免这样的编译器警告 Or is this an example of a pointless compiler warning that should just be ignored? 或者这是一个无意义的编译器警告的例子,应该被忽略?

I thought of two inelegant ways to avoid it. 我想到了避免它的两种不公平的方法。 I could use syntax like mystream.put( char(0xa4) ) on every call. 我可以在每次调用时使用mystream.put( char(0xa4) )等语法。 Or instead of using std::stringstream I could use std::basic_stringstream< unsigned char > , but I don't think that trick would work with std::ofstream , which is not a templated type. 或者不使用std::stringstream我可以使用std::basic_stringstream< unsigned char > ,但我认为这个技巧不适用于std::ofstream ,它不是模板化类型。 I feel like there should be a better solution here, especially since ofstream is meant for writing binary files. 我觉得这里应该有一个更好的解决方案,特别是因为ofstream用于编写二进制文件。

Your thoughts? 你的意见?

--EDIT-- - 编辑 -

Ah, I was mistaken about std::ofstream not being a templated type. 啊,我错了std::ofstream不是模板类型。 It is actually std::basic_ofstream<char> , but I tried that method that and realized it won't work anyway for lack of defined methods and polymorphic incompatibility with std::ostream . 它实际上是std::basic_ofstream<char> ,但我尝试了这种方法并且意识到它无论如何都不会因为缺少定义的方法和与std::ostream多态不兼容而起作用。

Here's a code sample: 这是一个代码示例:

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

I found solution that I'm happy with. 我找到了我很满意的解决方案。 It's more elegant than explicitly casting every constant to unsigned char . 它比将每个常量明确地转换为unsigned char更优雅。 This is what I had: 这就是我所拥有的:

ss.put( 0xa4 ); // C4309

I thought that the "truncation" was happening in implicitly casting unsigned char to char , but Cong Xu pointed out that integer constants are assumed to be signed, and any one greater than 0x7f gets promoted from char to int . 我认为“截断”是在隐式地将unsigned charchar ,但Cong Xu指出假定整数常量是有符号的,并且任何大于0x7f的都会从char提升为int Then it has to actually be truncated (cut down to one byte) if passed to put() . 然后,如果传递给put()它实际上必须被截断(减少到一个字节put() By using the suffix "u", I can specify an unsigned integer constant, and if it's no greater than 0xff, it will be an unsigned char . 通过使用后缀“u”,我可以指定无符号整数常量,如果它不大于0xff,则它将是unsigned char This is what I have now, without compiler warnings: 这就是我现在所拥有的,没有编译器警告:

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

As you've guessed, the problem is that ostream.put() expects a char , but 0x7F is the maximum value for char , and anything greater gets promoted to int . 正如您所猜测的那样,问题是ostream.put()需要一个char ,但0x7Fchar的最大值,而任何更大的值都会被提升为int You should cast to unsigned char , which is as wide as char so it'll store anything char does and safely, but also make truncation warnings legitimate: 您应该转换为unsigned char ,它与char一样宽,因此它将存储char所做的任何安全,但也会使截断警告合法:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM