2013-03-18 13 views
15

Programım, belirli bir metin olmayan dosya biçimine uygun olarak, bir dosyaya ikili veri yazma görevini yerine getiriyor. Yazmakta olduğum veriler zaten varolan bölümler içinde değil, bunun yerine byte byte ile çalışma zamanında birleştirildiğinden, yerine std::ostream::put() kullanıyorum. Bunun normal prosedür olduğunu farz ediyorum.Derleyici uyarısı C4309'dan kaçınmak için ortodox bir yol var mı - ikili dosya çıktısı ile "sabit değerin kesilmesi"?

Program gayet iyi çalışıyor. Argümanlar olarak iki basamaklı onaltılık tamsayı ile hem std::stringstream::put() hem de std::ofstream::put() kullanır. Ancak, put() argümanı 0x7f'den büyük olduğunda, C4309'un derleyici uyarısını "VC++ 2010'da" ("VC++ 2010'da") olarak alırım. Açıkçası, derleyici bir signed char bekleniyor ve sabit aralık dışı. Ama herhangi bir kesilmenin gerçekte olduğunu düşünmüyorum; Bayt, olması gerektiği gibi yazılır.

Derleyici uyarıları, normal ve kabul edilen bir şekilde bir şey yapmadığımı düşünmemi sağlıyor. Tanımladığım durumun ortak olması gerekiyor. gibi bir derleyici uyarısından kaçınmanın yaygın yolu var mı? Yoksa bu, göz ardı edilmemesi gereken bir anlamsız derleyici uyarısı örneğidir.

Ondan kaçınmanın iki yolunu düşünmüştüm. Her aramada mystream.put(char(0xa4)) gibi sözdizimini kullanabilirim. Veya std::stringstream kullanmak yerine std::basic_stringstream< unsigned char > kullanabilirdim, ancak bu hile, şablonlu bir tür değil std::ofstream ile çalışacağını düşünmüyorum. Burada daha iyi bir çözüm bulunmalı gibi hissediyorum, özellikle de ofstream ikili dosyalar yazmak içindir.

Düşünceleriniz?

--EDIT--

Ah, std::ofstream templated tip olmama konusunda yanıldı. Bu aslında std::basic_ofstream<char>'dur, ancak bu yöntemi denedim ve farkettim ki, std::ostream ile tanımlanmış yöntemler ve polimorfik uyumsuzluk nedeniyle işe yaramayacaktı. İşte

bir kod örneği verilmiştir:

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 
Tahmin ettiğimiz gibi
+4

Sadece bu kadar netiz, sorunuza somut bir kod örneği ekleyebilir misiniz? –

+1

Derleyici yazarların "anlamsız" uyarılar üretmek için zamanları olmadığından eminim. –

cevap

17

ben mutluyum çözüm buldu. Her sabiti unsigned char'a açıkça dökmekten daha zariftir.

ss.put(0xa4); // C4309 

ben "kesilme" char için unsigned char döküm örtülü oluyor düşündük ama Cong Xu sabitleri imzalanacak varsayılır o tamsayı işaret ve dışında herhangi bir fazla 0x7f alır: Bu ne vardı yani char'dan int'a yükseltilmiştir. Daha sonra, put()'a geçtiyse, aslında kesilmelidir (bir bayta kadar kesilir)."U" sonekini kullanarak, işaretsiz bir tamsayı sabiti belirtebilirim ve 0xff'den büyük değilse, unsigned char olacaktır. Derleyici uyarıları olmadan şu an sahip olduğum şey şu:

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

, sorun ostream.put() bir char beklediğini, ancak 0x7Fchar için maksimum değeridir ve fazla herhangi birşey int terfi alır . Sen kadar geniş char olarak hangi unsigned char için kullanması gereklidir yüzden güvenle yapar ve char şey saklamak edersiniz ancak meşru kesme uyarıları yapmak:

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

Neden 'ss.put (static_cast (0x80));' 'ss.put (imzasız char (0x80))' veya 'ss.put ((imzasız char) 0x80)' yerine kullanıyorsunuz? Bir sebepten dolayı tercih edilen statik bir döküm mü? –

+1

@SamKauffman, bu sadece cast yapmak için modern C++ yoludur. Daha kötü ama daha az belirsiz ve daha güvenli. –

+0

@CongXu, teşekkürler! Tanıtım hakkında yazdıklarınız, hangi kesintinin gerçekte devam ettiğini anlamamı sağladı. –

İlgili konular