C++字符串类型混淆

c++ string types confusion

我在我的 .cpp 程序中包含以下文件:

#include <windows.h>
#include <tchar.h>
#include <stdio.h>

然而,当我写

LPCTSTR pMsg;
DWORD msgLen;
...
msgLen = _tcslen(pMsg);

编译器提示如下错误:

C2664: 'size_t strlen(const char *)' : cannot convert argument 1 from 'LPCTSTR' to 'const char *' Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

当然,我可以通过转换为 LPCSTR 或使用 wcslen 轻松解决问题。但那是不对的,编译器不应该根据宏 UNICODE 自己决定所有这些东西吗?肯定是定义好了,因为我在文件开头写#define UNICODE的时候,编译器提示warning,说已经定义了。那问题是什么?为什么它选择 strlen 而不是 wcslen

这里是实际的代码:

BOOL PrintString(HANDLE hOut, ...)
{
    DWORD msgLen, count;
    LPCTSTR pMsg;
    va_list pMsgList;
    va_start(pMsgList, hOut);
    while((pMsg = va_arg(pMsgList, LPCTSTR)) != NULL)
    {
        msgLen = _tcslen(pMsg);
        if(!WriteConsole(hOut, pMsg, msgLen, &count, NULL) && !WriteFile(hOut, pMsg, msgLen*sizeof(TCHAR), &count, NULL))
        {
            va_end(pMsgList);
            return FALSE;
        }
    }
    va_end(pMsgList);
    return TRUE;
}

我都试过了,#define _UNICODE#define _UNICODE 但都没有用。而且,#define _UNICODE提示已经定义的警告

_tcslen 正在扩展到 strlenLPCTSTR 正在扩展到 const wchar_t*。这意味着您对 _UNICODEUNICODE 的定义不一致。前者被TCHAR头文件使用,后者被Windows头文件使用。鉴于您更新的问题,我会说您已定义 UNICODE_UNICODE 未定义。

除此之外,您应该不使用 TCHAR 让您的生活更轻松。当您需要能够为 Win9x 和 WinNT 编译单个源代码时,这很有用。现在你可能不以 Win9x 为目标。所以我的建议是简单地删除所有 TCHAR 的使用,让你的代码更简单。

根据 MSDN,_tcslen 扩展到的内容由宏 _UNICODE. LPCTSTR, on the other hand, is controlled by UNICODE 控制。确保你有一致定义的这两个宏,并且在包含任何可能使用它们的 header 之前。