unsigned char和char指针之间的区别

时间:2012-02-10 13:44:54

标签: c++ char byte atl unsigned-char

我对unsigned char(在WinAPI中也是BYTE)和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());
}

所以,问题:

  • BYTE*LPCSTRconst char*)的C风格演员是否对所有可能的案件都安全?

  • 将数组数据转换为宽字符串时,是否真的有必要添加 double 空终止?

  • 转化例程CStringW((LPCWSTR)copiedArray.GetData())对我来说似乎无效,是真的吗?

  • 如何让所有这些代码更易于理解和维护?

4 个答案:

答案 0 :(得分:3)

对于字节的定义,C标准有点奇怪。你确实有几个保证。

  • 一个字节的大小始终为一个字符
    • sizeof(char)始终返回1
  • 一个字节大小至少为8位

这个定义与字节长度为6或7位的旧平台不能很好地融合,但它确实意味着BYTE*,char *保证是等价的。

Unicode字符串末尾需要多个空值,因为有一些有效的Unicode字符以零(空)字节开头。

至于使代码更容易阅读,这完全是一种风格问题。此代码似乎是以许多旧的C Windows代码使用的样式编写的,这些代码肯定不受欢迎。可能有很多方法可以让你更清楚,但如何让它更清晰没有明确的答案。

答案 1 :(得分:2)

  • 是的,它总是安全的。因为它们都指向一个单字节内存位置数组 LPCSTR:指向Const的长指针(单字节)字符串
    LPCWSTR:指向宽范围(多字节)字符串的长指针
    LPCTSTR:指向Const上下文的长指针(单字节或多字节)字符串

  • 在宽字符串中,每个字符占用2个字节的内存,包含字符串的内存位置长度必须是2的倍数。因此,如果要添加宽'\ 0'到在字符串的结尾处,您应该添加两个字节。

  • 对不起这部分,我不知道ATL,我在这方面无法帮助你,但实际上我认为这里没有复杂性,而且我觉得它很容易维护。您真正希望使用哪些代码更容易理解和维护?

答案 2 :(得分:1)

  1. 如果BYTE *的行为类似于正确的字符串(即最后一个BYTE为0),则可以将BYTE *转换为LPCSTR,是的。使用LPCSTR的函数假定以零结尾的字符串。
  2. 我认为只有在处理一些多字节字符集时才需要多个零。最常见的8位编码(如普通的Windows Western和UTF-8)不需要它们。
  3. CString是微软对用户友好字符串的最佳尝试。例如,无论CString本身是否宽泛,其构造函数都可以处理charwchar_t类型的输入,因此您不必担心转换太多。
  4. 编辑:等等,现在我看到他们正在滥用BYTE数组来存储宽字符。我不能推荐。

答案 3 :(得分:0)

LPCWSTR是一个字符串,每个字符有2个字节,“char”是每个字符一个字节。这意味着你不能用C风格转换它,因为你必须调整内存(在每个标准ASCII之前添加一个“0”),而不只是以与内存不同的方式读取数据(什么是C-Cast)会做)。 因此演员阵容不那么安全。

Double-Nulltermination:您总是将2个字节作为一个字符,因此您的“字符串结束”符号必须为2个字节长。

为了使代码更易于理解,请参阅Boost中的lexical_cast(http://www.boost.org/doc/libs/1_48_0/doc/html/boost_lexical_cast.html)

另一种方法是使用std :: strings(使用类似std :: basic_string;),你可以执行String操作。