[英]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 char
为char
,但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
,但0x7F
是char
的最大值,而任何更大的值都会被提升为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.