Есть ли ортодоксальный способ избежать предупреждения компилятора C4309 — «усечение постоянного значения» с выводом двоичного файла?

Моя программа выполняет обычную задачу записи двоичных данных в файл, соответствующий определенному нетекстовому формату файла. Поскольку данные, которые я пишу, уже не находятся в существующих блоках, а вместо этого собраны побайтно во время выполнения, я использую std::ostream::put() вместо write(), Я предполагаю, что это нормальная процедура.

Программа работает просто отлично. Он использует оба std::stringstream::put() а также std::ofstream::put() с двузначными шестнадцатеричными целыми числами в качестве аргументов. Но я получаю предупреждение компилятора C4309: «усечение постоянного значения» (в 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

15

Решение

Я нашел решение, которым я доволен. Это более элегантно, чем явное приведение каждой константы к unsigned char, Вот что у меня было:

ss.put( 0xa4 ); // C4309

Я думал, что «усечение» происходило в неявном приведении unsigned char в char, но Конг Сюй указал, что целочисленные константы считаются подписанными, и любое значение, большее 0x7f, повышается с char в int, Затем он должен быть фактически обрезан (сокращен до одного байта), если передан put(), Используя суффикс «u», я могу указать целочисленную константу без знака, и если она не больше 0xff, это будет unsigned char, Это то, что я сейчас имею, без предупреждений компилятора:

ss.put( 0xa4u );
17

Другие решения

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

Как вы уже догадались, проблема в том, что ostream.put() ожидает char, но 0x7F максимальное значение для charи что-либо большее становится int, Вы должны бросить на unsigned char, который так же широк, как char так что он будет хранить что угодно char делает и безопасно, но также делает предупреждения усечения законными:

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

По вопросам рекламы [email protected]