LPSTR LPCTSTR解释
LPSTR LPCTSTR explanation
我有以下 C++ 代码:
#include "stdafx.h"
#include <atlstr.h>
int _tmain(int argc, _TCHAR* argv[])
{
CString OFST_PATH;
TCHAR DIR_PATH[MAX_PATH];
GetCurrentDirectory(MAX_PATH, DIR_PATH);
OFST_PATH.Format(DIR_PATH);
CHAR *pOFST_PATH = (LPSTR)(LPCTSTR)OFST_PATH;
return 0;
}
想明白为什么程序最后pOFST_PATH
的值是"c"? (LPSTR)(LPCTSTR)
变量 OFST_PATH
的转换对其中写入的整个路径做了什么?
正如您在下面window中看到的,调试时变量值是:
CString
和 LPCTSTR
都基于 TCHAR
,当定义了 UNICODE
时,它是 wchar_t
(在您的情况下,正如我可以通过调试器中 argv
的值判断的那样)。当您这样做时:
(LPCTSTR)OFST_PATH
可以正常工作,因为 CString
有一个到 LPCTSTR
的转换运算符。但是如果定义了 UNICODE
,LPCTSTR
就是 LPCWSTR
、a.k.a。 wchar_t const*
。它指向一个 utf16 字符数组。该数组中的第一个字符是 L'c'
(这是 'c'
的宽字符版本)。 L'c'
的字节在内存中看起来像这样:0x63 0x00
。这是字母 'c' 的 ASCII 代码,后跟一个零。因此,当您将 CString
转换为 LPCTSTR
时,这是有效的,但是,您的下一次转换:
(LPSTR)(LPCTSTR)OFST_PATH
这是无效的。 LPSTR
是 char*
,因此您将 wchar_t const*
视为 char*
。好吧,您的调试器假定当它看到 char*
时,它正在查看一个空终止的窄字符串。如果你记得上面第一个字符的字节值是什么,它是字母 'c' 的 ASCII 值,后跟一个零。因此调试器将其视为仅由字母 'c'.
组成的空终止字符串
这个故事的寓意是,如果您不了解它们的作用以及它们是否合适,请不要使用 C 风格的强制转换。
我有以下 C++ 代码:
#include "stdafx.h"
#include <atlstr.h>
int _tmain(int argc, _TCHAR* argv[])
{
CString OFST_PATH;
TCHAR DIR_PATH[MAX_PATH];
GetCurrentDirectory(MAX_PATH, DIR_PATH);
OFST_PATH.Format(DIR_PATH);
CHAR *pOFST_PATH = (LPSTR)(LPCTSTR)OFST_PATH;
return 0;
}
想明白为什么程序最后pOFST_PATH
的值是"c"? (LPSTR)(LPCTSTR)
变量 OFST_PATH
的转换对其中写入的整个路径做了什么?
正如您在下面window中看到的,调试时变量值是:
CString
和 LPCTSTR
都基于 TCHAR
,当定义了 UNICODE
时,它是 wchar_t
(在您的情况下,正如我可以通过调试器中 argv
的值判断的那样)。当您这样做时:
(LPCTSTR)OFST_PATH
可以正常工作,因为 CString
有一个到 LPCTSTR
的转换运算符。但是如果定义了 UNICODE
,LPCTSTR
就是 LPCWSTR
、a.k.a。 wchar_t const*
。它指向一个 utf16 字符数组。该数组中的第一个字符是 L'c'
(这是 'c'
的宽字符版本)。 L'c'
的字节在内存中看起来像这样:0x63 0x00
。这是字母 'c' 的 ASCII 代码,后跟一个零。因此,当您将 CString
转换为 LPCTSTR
时,这是有效的,但是,您的下一次转换:
(LPSTR)(LPCTSTR)OFST_PATH
这是无效的。 LPSTR
是 char*
,因此您将 wchar_t const*
视为 char*
。好吧,您的调试器假定当它看到 char*
时,它正在查看一个空终止的窄字符串。如果你记得上面第一个字符的字节值是什么,它是字母 'c' 的 ASCII 值,后跟一个零。因此调试器将其视为仅由字母 'c'.
这个故事的寓意是,如果您不了解它们的作用以及它们是否合适,请不要使用 C 风格的强制转换。