2012-02-10 24 views
4

私は、unsigned char(WinAPIでは​​)とcharポインタの違いを少し混同しています。符号なしのcharポインタとcharポインタの違い

は現在、私はいくつかのATLベースのレガシーコードで働いていると私は、次のような表現の多くを参照してください。

CAtlArray<BYTE> rawContent; 
CALL_THE_FUNCTION_WHICH_FILLS_RAW_CONTENT(rawContent); 
return ArrayToUnicodeString(rawContent); 
// or return ArrayToAnsiString(rawContent); 

を今、ArrayToXXStringの実装は次のように見えますだから、

CStringA ArrayToAnsiString(const CAtlArray<BYTE>& array) 
{ 
    CAtlArray<BYTE> copiedArray; 
    copiedArray.Copy(array); 
    copiedArray.Add('\0'); 

    // Casting from BYTE* -> LPCSTR (const char*). 
    return CStringA((LPCSTR)copiedArray.GetData()); 
} 

CStringW ArrayToUnicodeString(const CAtlArray<BYTE>& array) 
{ 
    CAtlArray<BYTE> copiedArray; 
    copiedArray.Copy(array); 

    copiedArray.Add('\0'); 
    copiedArray.Add('\0'); 

    // Same here.   
    return CStringW((LPCWSTR)copiedArray.GetData()); 
} 

質問:

  • すべての可能な場合のためにLPCSTRからBYTE*からCスタイルのキャスト(const char*)安全ですか?

  • アレイデータをワイド文字列に変換するときに実際に追加する必要がありますか?

  • 変換ルーチンCStringW((LPCWSTR)copiedArray.GetData())は私には無効に見えますが、それは本当ですか?

  • このコードをすべて理解しやすく保守する方法はありますか?

答えて

3

Cの標準は、バイトの定義に関しては奇妙です。あなたはしかし、保証のカップルを持っています。バイトは常に

  • はsizeof(文字)のサイズが1つの文字であろうことは常にバイトのサイズは、少なくとも8ビット

この定義であろう1

  • を返し

    • バイトが6ビットまたは7ビットの古いプラットフォームではうまく網羅できませんが、BYTE*,char *は同等であることが保証されています。

      ゼロ(ヌル)バイトで始まる有効なUnicode文字があるため、Unicode文字列の末尾に複数のNULLが必要です。

      コードを読みやすくするために、それは完全にスタイルの問題です。このコードは、古いC言語の多くのコードで使用されているスタイルで書かれているようです。それをもっと明確にする方法はおそらくたくさんありますが、明確にする方法は明確な答えがありません。

  • 2
    • はい、それは常に安全です。彼らは両方とも1バイトのメモリ位置の配列を指しているからです。
      LPCSTRます。Constに長いポインタ(半角)文字列
      LPCWSTR:ロングポインタワイド(マルチバイト)文字列
      LPCTSTR CONSTするます。Constコンテキスト依存(シングルバイトまたはマルチバイト)文字列に長いポインタ

    • ワイド文字列ではすべての1文字が2バイトのメモリを占有し、文字列を含むメモリ位置の長さは2の倍数でなければなりません。したがって、ワイド '\ 0'を文字列の最後に2バイトを追加する必要があります。

    • この部分について申し訳ありませんが、私はATLを知らず、この部分であなたを助けることはできませんが、実際にはここには複雑さは見当たりません。どのようなコードを本当に理解して維持しやすくしたいですか?

    1
    1. BYTEは、*(すなわち、最後のバイトが0である)適切な文字列と同じように動作している場合は、[はい、LPCSTRにBYTE *をキャストすることができます。 LPCSTRで機能する関数は、ゼロ終了文字列を仮定します。
    2. マルチバイト文字セットを扱うときに複数のゼロが必要なのは私だけだと思います。最も一般的な8ビットエンコーディング(通常のWindows WesternやUTF-8など)は、それらを必要としません。
    3. CStringは、ユーザーフレンドリーな文字列でのMicrosoftの最高の試みです。例えば、そのコンストラクタは、CString自体が広いかどうかにかかわらず、charwchar_tの型入力を扱うことができるので、変換についてはあまり心配する必要はありません。

    編集:今、私はそれらが広い文字を格納するBYTE配列を乱用しているのを見ています。私はそれをお勧めできませんでした。

    0

    LPCWSTRは1文字あたり2バイトの文字列で、「char」は1文字あたり1バイトです。つまり、メモリを調整する必要がある(各標準ASCIIの前に "0"を加えて)、メモリとは別の方法でデータを読み込むだけではなく、Cスタイルでキャストすることができないということです。するだろう)。 キャストはあまり安全ではないと私は言うだろう。

    ダブルNulltermination:常に2バイトを1文字として扱うので、 "End-of-string"記号は2バイト長でなければなりません。 (http://www.boost.org/doc/libs/1_48_0/doc/html/boost_lexical_cast.html)ブーストでのlexical_cast世話を理解するためにそのコードを容易にするために

    使用されるだろうもう一つの方法std :: strings(std :: basic_string;のように使用します)を使用して、String操作を実行できます。

    関連する問題