【问题标题】:Difference between unsigned char and char pointersunsigned char 和 char 指针的区别
【发布时间】:2012-03-02 23:26:08
【问题描述】:

我对@9​​87654321@(在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*LPCSTR (const char*) 的C 风格转换是否适用于所有可能的情况?

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

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

  • 有什么方法可以让所有这些代码更易于理解和维护?

【问题讨论】:

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


    【解决方案1】:

    当涉及到字节的定义时,C 标准有点奇怪。不过,您确实有几个保证。

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

    此定义与字节长度为 6 或 7 位的旧平台不太吻合,但它确实意味着 BYTE*,char * 保证是等效的。

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

    至于让代码更易于阅读,那完全是风格问题。这段代码似乎是用许多旧的 C Windows 代码所使用的风格编写的,这种风格肯定已经失宠了。可能有很多方法可以让你更清楚,但如何让它更清楚却没有明确的答案。

    【讨论】:

      【解决方案2】:
      • 是的,它总是安全的。因为它们都指向一个单字节内存位置数组。
        LPCSTR:指向常量(单字节)字符串的长指针
        LPCWSTR:指向常量宽(多字节)字符串的长指针LPCTSTR : 指向 Const 上下文相关(单字节或多字节)字符串的长指针

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

      • 抱歉这部分,我不知道 ATL,我无法在这部分为您提供帮助,但实际上我认为这里没有复杂性,而且我认为它很容易维护。您真正想让哪些代码更易于理解和维护?

      【讨论】:

        【解决方案3】:
        1. 如果 BYTE* 的行为类似于正确的字符串(即最后一个 BYTE 为 0),则可以将 BYTE* 强制转换为 LPCSTR,是的。使用 LPCSTR 的函数假定以零结尾的字符串。
        2. 我认为只有在处理某些多字节字符集时才需要多个零。最常见的 8 位编码(如普通的 Windows Western 和 UTF-8)不需要它们。
        3. CString 是微软对用户友好字符串的最佳尝试。比如它的构造函数可以同时处理charwchar_t类型的输入,不管CString本身是不是宽的,所以你不用太担心转换。

        编辑:等等,现在我看到他们正在滥用 BYTE 数组来存储宽字符。我不建议这样做。

        【讨论】:

          【解决方案4】:

          LPCWSTR 是每个字符 2 个字节的字符串,“char”是每个字符一个字节。这意味着您不能将其转换为 C 样式,因为您必须调整内存(在每个标准 ASCII 之前添加一个“0”),而不仅仅是以与内存不同的方式读取数据(什么是 C-Cast会做)。 所以我会说演员阵容并不那么安全。

          双空终止:一个字符总是有 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 操作。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2014-05-03
            • 1970-01-01
            • 2016-07-07
            • 1970-01-01
            • 2020-12-23
            • 1970-01-01
            • 1970-01-01
            • 2020-10-08
            相关资源
            最近更新 更多