TCHAR szExeFileName[MAX_PATH];
GetModuleFileName(NULL, szExeFileName, MAX_PATH);
CString tmp;
lstrcpy(szExeFileName, tmp);
CString out;
out.Format("\nInstall32 at %s\n", tmp);
TRACE(tmp);
错误(格式化):
error C2664: 'void ATL::CStringT<BaseType,StringTraits>::Format(const wchar_t
*,...)' : cannot convert parameter 1 from 'const char [15]' to 'const wchar_t
我只想获取启动此程序的当前路径并将其复制到CString中,以便我可以在其他地方使用它。我目前正试图通过TRACE来看看它的路径。但字符串,字符,字符数组,我不可能得到所有的海峡。有人可以给我一个指针吗?
答案 0 :(得分:9)
接受的答案解决了这个问题。但问题还要求更好地理解Windows上所有字符类型之间的差异。
<强>编码强>
Windows上的char
(几乎所有其他系统)都是单字节。一个字节通常被解释为无符号值[0..255]或有符号值[-128..127]。 (较旧的C ++标准保证只有[-127..127]的有符号范围,但大多数实现给出[-128..127]。我相信C ++ 11保证更大的范围。)
ASCII是[0..127]范围内的值到特定字符的字符映射,因此您可以将ASCII字符存储在有符号字节或无符号字节中,因此它始终适合{{ 1}}。
但ASCII并不具备大多数语言所需的所有字符,因此通常使用字节中可用的其余值来扩展字符集,以表示某些语言(或某些语言)所需的其他字符。语言)。因此,虽然[0..127]几乎总是意味着相同的东西,但像150这样的值只能在特定编码的上下文中解释。对于单字节字母表,这些编码称为代码页。
代码页有所帮助,但它们并没有解决所有问题。您始终必须知道特定文档使用哪个代码页才能正确解释它。此外,您通常无法编写使用不同语言的单个文档。
此外,某些语言的字符数超过256个,因此无法将一个char
映射到一个字符。这导致了多字节字符编码的发展,其中[0..127]仍然是ASCII,但是其他一些值是&#34;转义&#34;这意味着你必须查看一些以下char
来确定你真正拥有的角色。 (最好将多字节视为变量 - 字节,因为有些字符只需要一个字节,而其他字符只需要两个或更多字节。)多字节有效,但它可以使用多字节。为代码而痛苦。
与此同时,内存变得越来越丰富,因此许多组织聚集在一起创建了Unicode,其目标是将值通用映射到字符(对于#34;字符&#34;的适当模糊定义)。最初,人们相信所有角色(或者至少是所有人都会使用的角色)都适合16位值,这很好,因为你不必处理多字节编码 - 你&# 39; d每个字符只使用两个字节而不是一个字节。大约在这个时候,微软决定采用Unicode作为Windows中文本的内部表示。
<强> WCHAR 强>
因此,Windows有一个名为char
的类型,一个双字节值,表示&#34; Unicode&#34; &#34;字符&#34 ;.我在这里使用引号因为Unicode已经过了原始的双字节编码,所以Windows调用了什么&#34; Unicode&#34;今天并不是真正的Unicode - 它实际上是Unicode的特定编码,称为UTF-16。一个&#34;字符&#34;在Unicode中并不像在ASCII中那样简单,因为在某些语言中,字符以有趣的方式组合或以其他方式影响相邻字符。
较新版本的Windows在内部使用了这些16位WCHAR
值的文本,但是仍有大量代码用于单字节代码页,甚至还有一些代码用于多字节编码。这些程序仍然使用WCHAR
而不是char
s。其中许多程序必须与使用旧版Windows的人一起使用,这些Windows仍在内部使用WCHAR
以及使用char
的新版本。因此,设计了一种使用C宏和typedef的技术,以便您可以以一种方式编写代码,并在编译时选择使用WCHAR
或char
。
<强> TCHAR 强>
为了实现这种灵活性,您可以使用WCHAR
作为&#34;文本字符&#34;。在某些头文件(通常为TCHAR
)中,<tchar.h>
可以是TCHAR
或char
的typedef,具体取决于编译时环境。 Windows标头采用了这样的约定:
WCHAR
是指向LPTSTR
s。TCHAR
是指向LPWSTR
s。WCHAR
是指向LPSTR
s。(char
for&#34; long&#34;是16位日的剩余时间,当时我们有长,远,近指针。这些都已经过时,但是{{1前缀倾向于保留。)
获取和返回字符串的大多数Windows API函数实际上都替换为两个版本:L
版本(用于&#34; ANSI&#34;字符)和L
版本(用于广泛的人物)。 (同样,历史遗留在这些中显示。代码页方案通常被称为ANSI代码页,尽管我们从来都不清楚它们是否真的被ANSI标准所统治。)
因此,当您调用这样的Windows API时:
A
您真正在做的是调用扩展为W
或SetWindowText(hwnd, lptszTitle);
的预处理器宏。它应该与SetWindowTextA
定义一致。也就是说,如果您想要SetWindowTextW
个字符串,那么您将获得TCHAR
版本,如果您想要char
个字符串,则可以获得A
版本
但由于字符串文字,它有点复杂。如果你这样写:
WCHAR
然后只有在您定位W
版本时才会编译,因为SetWindowText(hwnd, "Hello World"); // works only in "ANSI" mode
是char
s的字符串,所以它只与"Hello World"
兼容char
版本。如果您想要SetWindowTextA
版本,则必须写:
WCHAR
此处SetWindowText(hwnd, L"Hello World"); // only works in "Unicode" mode
表示您需要宽字符。 (L
实际上代表很长,但它与上面的长指针有着不同的长度感。)当编译器在字符串上看到L
前缀时,它知道该字符串应该是编码为一系列L
而不是wchar_t
s。
(针对Windows的编译器使用char
的双字节值,这恰好与Windows定义的wchar_t
相同。针对其他系统的编译器通常使用{{1}的四字节值1}},这是保存单个Unicode代码点所需要的。)
因此,如果您想要能够以任何方式编译的代码,则需要另一个宏来包装字符串文字。有两种选择:WCHAR
和wchar_t
。它们的工作方式完全相同。第一个来自编译器库,第二个来自OS的库。所以你写这样的代码:
_T()
如果您定位TEXT()
,则该宏是一个只返回常规字符串文字的无操作。如果您定位SetWindowText(hwnd, TEXT("Hello World")); // compiles in either mode
,则宏会预先设置char
。
那么如何告诉编译器你想要定位WCHAR
?您可以定义L
和WCHAR
。前者用于Windows API,后者用于编译器库。确保你永远不要定义另一个。
答案 1 :(得分:3)
我的猜测是你在Unicode模式下编译。
尝试将格式字符串括在_T宏中,该宏旨在提供始终正确的方法来提供常量字符串参数,无论您是以Unicode还是ANSI模式进行编译:
out.Format(_T("\nInstall32 at %s\n"), tmp);