0

いくつかのコードをクリーンアップしようとしていますが、uint16_tをwchar_tにキャストする安全な方法が次のとおりかどうかを知りたいと思いました。

#if ! defined(MARKUP_SIZEOFWCHAR)
#if __SIZEOF_WCHAR_T__ == 4 || __WCHAR_MAX__ > 0x10000
#define MARKUP_SIZEOFWCHAR 4
#else
#define MARKUP_SIZEOFWCHAR 2
#endif

void FileReader::parseBuffer(char * buffer, int length)
{
  //start by looking for a vrsn
  //Header seek around for a vrns followed by 32 bit size descriptor
  //read 32 bits at a time
  int cursor = 0;
  char vrsn[5] = "vrsn";
  cursor = this->searchForMarker(cursor, length, vrsn, buffer);
  int32_t size = this->getObjectSizeForMarker(cursor, length, buffer);
  cursor = cursor + 7; //advance cursor past marker and size
  wchar_t *version = this->getObjectForSizeAndCursor(size, cursor, buffer);
  wcout << version;
  delete[] version; //this pointer is dest from getObjectForSizeAndCursor
}

-

wchar_t* FileReader::getObjectForSizeAndCursor(int32_t size, int cursor, char *buffer) {

  int wlen = size/2;
  uint32_t *dest = new uint32_t[wlen+1];
  unsigned char *ptr = (unsigned char *)(buffer + cursor);
  for(int i=0; i<wlen; i++) {
    #if MARKUP_SIZEOFWCHAR == 4 // sizeof(wchar_t) == 4
      char padding[2] = {'\0','\0'}; 
      dest[i] =  (padding[0] << 24) + (padding[1] << 16) + (ptr[0] << 8) + ptr[1];
    #else // sizeof(wchar_t) == 2
      dest[i] = (ptr[0] << 8) + ptr[1];
    #endif
      ptr += 2;
      cout << ptr;
  }
  return (wchar_t *)dest;
}

パディングの使用方法にスコーピングの問題がありますか?delete dest[]呼び出し元の関数でパディングをリークしますか?

4

2 に答える 2

0

あなたがやろうとしていることはうまくいきません。いくつかの点で壊れていますが、キャストに焦点を当てましょう。

あなたの質問はあなたのコードと一致しません。あなたのコードはを使用してuint32_tいますが、あなたの質問は。について尋ねていuint16_tます。しかし、どちらも機能しないため、それは問題ではありません。

を使用する必要がある場合はwchar_t、実際にを使用 wchar_tする必要があります。目標がaの2つの連続したバイトを取得char*し、それらをaの最初の2バイトにコピーすることであるwchar_t場合は、それを実行します。

これは、実際に機能するコードのはるかに優れたバージョンです(aから2バイトをコピーして、それがchar*であるかのように見せかけるのが理にかなっている程度までwchar_t)。

std::wstring FileReader::getObjectForSizeAndCursor(int32_t size, int cursor, char *buffer) {

  int wlen = size/2;
  std::wstring out(wlen);
  unsigned char *ptr = (unsigned char *)(buffer + cursor);
  for(int i=0; i<wlen; i++) {
    out[i] = (ptr[0] << 8) + ptr[1];
    ptr += 2;
    cout << ptr;
  }
  return out;
}

さらに、のような適切なRAIIクラスを使用しているため、メモリリークが発生する可能性はありませんstd::wstring

于 2012-10-07T18:10:35.730 に答える
0

区別

#if MARKUP_SIZEOFWCHAR == 4 // sizeof(wchar_t) == 4
  char padding[2] = {'\0','\0'}; 
  dest[i] =  (padding[0] << 24) + (padding[1] << 16) + (ptr[0] << 8) + ptr[1];
#else // sizeof(wchar_t) == 2
  dest[i] = (ptr[0] << 8) + ptr[1];
#endif

完全に不要です。padding[i]は0なので、左にシフトすると0のままになり、追加しても効果はありません。

コンパイラーは、paddingループの反復ごとに2バイト配列の割り当てを最適化する場合としない場合がありますが、自動配列であるため、リークすることはありません。

ループで使用される型は符号なしであるため、単に

dest[i] = (ptr[0] << 8) + ptr[1];

完全に安全です。(もちろん、エンディアンは正しくなければなりません。)

にとって

return (wchar_t *)dest;

タイプをdestのサイズに依存させる必要があります。if (および)wchar_tである必要があります。uint16_t*sizeof(wchar_t) == 2CHAR_BIT == 8

于 2012-10-07T18:01:18.987 に答える