5

( WinAPIにunsigned charもあります)とポインタの違いに少し混乱しています。BYTEchar

現在、いくつかの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());
}

だから、質問:

  • CスタイルのキャストfromBYTE*からLPCSTRconst char*)は、考えられるすべてのケースで安全ですか?

  • 配列データをワイド文字列に変換するときに、二重のヌル終了を追加する必要が本当にありますか?

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

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

4

4 に答える 4

3

バイトの定義に関しては、C標準はちょっと奇妙です。ただし、いくつかの保証があります。

  • バイトは常に1文字のサイズになります
    • sizeof(char)は常に1を返します
  • バイトは少なくとも8ビットのサイズになります

この定義は、バイトが6ビットまたは7ビットの長さであった古いプラットフォームとはうまく一致しませんが、それは意味がBYTE*,あり、char *同等であることが保証されています。

ゼロ(null)バイトで始まる有効なUnicode文字があるため、Unicode文字列の最後に複数のnullが必要です。

コードを読みやすくすることに関しては、それは完全にスタイルの問題です。このコードは、多くの古いC Windowsコードで使用されているスタイルで記述されているように見えますが、これは間違いなく支持されていません。あなたにとってそれをより明確にする方法はおそらくたくさんありますが、それをより明確にする方法には明確な答えがありません。

于 2012-02-10T14:09:47.210 に答える
2
  • はい、常に安全です。どちらもシングルバイトのメモリ位置の配列を指しているためです。
    LPCSTR:定数へのロングポインタ(シングルバイト)文字列
    LPCWSTR:定数へのロングポインタワイド(マルチバイト)文字列
    LPCTSTR:定数へのロングポインタコンテキスト依存(シングルバイトまたはマルチバイト)文字列

  • ワイド文字列では、すべての1文字が2バイトのメモリを占有し、文字列を含むメモリ位置の長さは2の倍数である必要があります。したがって、文字列の末尾に幅の広い「\ 0」を追加する場合は、 2バイトを追加する必要があります。

  • この部分については申し訳ありませんが、私はATLを知らないので、この部分についてはお手伝いできませんが、実際にはここでは複雑さは見られず、保守は簡単だと思います。どのコードを本当に理解し、維持しやすくしたいですか?

于 2012-02-10T14:05:54.393 に答える
1
  1. BYTE *が適切な文字列のように動作する場合(つまり、最後のBYTEが0の場合)、BYTE*をLPCSTRにキャストできます。LPCSTRで動作する関数は、ゼロで終了する文字列を想定しています。
  2. 複数のゼロは、いくつかのマルチバイト文字セットを処理する場合にのみ必要だと思います。最も一般的な8ビットエンコーディング(通常のWindows WesternやUTF-8など)はそれらを必要としません。
  3. これCStringは、ユーザーフレンドリーな文字列に対するMicrosoftの最善の試みです。たとえば、そのコンストラクターは、CString自体がワイドであるかどうかに関係なく、入力charと型の両方を処理できるため、変換についてあまり心配する必要はありません。wchar_t

編集:待ってください。ワイド文字を格納するためにBYTE配列を悪用していることがわかります。これはお勧めできません。

于 2012-02-10T14:07:02.457 に答える
0

LPCWSTRは、1文字あたり2バイトの文字列であり、「char」は1文字あたり1バイトです。つまり、メモリを調整する必要があるため(各標準ASCIIの前に「0」を追加)、メモリとは異なる方法でデータを読み取るだけでなく(C-Cast)、Cスタイルでキャストすることはできません。するだろう)。ですから、キャストはそれほど安全ではありません。

ダブルヌルターミネーション:1文字として常に2バイトがあるため、「文字列の終わり」記号は2バイトの長さである必要があります。

そのコードを理解しやすくするために、Boost(http://www.boost.org/doc/libs/1_48_0/doc/html/boost_lexical_cast.html)でlexical_castの世話をしてください。

もう1つの方法は、std :: stringsを使用することです(std :: basic_string;のように使用します)。これにより、String操作を実行できます。

于 2012-02-10T14:07:20.133 に答える