您的位置:首页 > 其它

不要在接口定义中使用 TCHAR 字符串

2009-09-29 14:37 274 查看
先上个图,July 早期版本的“运行”对话框。



其实在我最初的构想中,这个对话框的提示文字并不是系统默认的文字,而应该是我写上去的——最起码把“Windows”替换成 “July”。
但是我最后放弃了,因为我写上去的字到最后显示出来是乱码。由于 RunFileDlg 这个 API 并没有详细的文档支持,而且其时的我也没有任何逆向的能力,所以干脆把文本参数给了个 NULL,直接用默认提示算球了。

现在回想起来其实是 TCHAR 惹的祸。在当时,我从网上得到的 RunFileDlg 声明是类似这个样子:

int WINAPI RunFileDlg(
    HWND hwndParent,
    HICON hIcon, 
    LPCTSTR pszWorkingDir,
    LPCTSTR pszTitle,
    LPCTSTR pszPrompt,
    DWORD dwFlags
);


我的开发环境是 VC6,工程设置没改过。于是一调用,乱码个球了。因为 RunFileDlg 的字符串参数实际上是 LPCWSTR,而 VC6 默认会把 LPCTSTR 定义为 LPCSTR。

我想,现在该重新审视一下 TCHAR 的意义了。它,以及 LPTSTR、LPCTSTR 都是一个 typedef,而并非一个具体的类型。它会随着编译器是否定义了 UNICODE 宏而指向真正的类型,也就是 WCHAR 或 char。换句话说,TCHAR 的确实现了 Unicode 和 ANSI 编码的兼容,但这种兼容是在源代码一级的,在编译好的 PE 可执行映像中,该是什么还是什么。考虑下面的代码:
char str[32];
lstrcpy(str, "Hello, World");


我曾见过无数类似的代码,甚至我也这么写过。在 ANSI 的编译环境下,这么写是没问题的,但是如果定义了 UNICODE,那么这段代码就会收到编译错误,因为 lstrcpy 将会被定义成 lstrcpyW,需求的参数类型是 LPWSTR 和 LPCWSTR。

也许你会说:我自己有能力控制我的源代码,知道自己用的是 lstrcpyA 还是 lstrcpyW,你管得着么?

的确,这是你的自由,我也不会干涉你的代码风格,更不会质疑你对代码的控制力。

但是,如果你的代码要提供给别人,而且你提供的只是一个接口;甚至,这个接口跨越了 PE 边界,那你总应该负点责吧?

别让你那含混不清的 TCHAR 给你们双方都带来麻烦。

----------传说中的分隔线----------

如果我提供给你一个 .dll 和一个 .h,而这个 .h 中的接口定义是用 TCHAR 来描述的,那会发生什么事?

你分别写 A 和 W 的两套代码来测试这个 TCHAR 到底代表 char 还是 WCHAR。这麻烦了你。

你直接问我这个 TCHAR 代表什么。这麻烦了我们俩。

所以,何必呢?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐