wchar_t是内置还是别名(亲测有效:wchar_t在windows下是16位整数的别名,在linux等平台下是32位整数的别名。MSVC2008开始默认是/Zc:wchar_t)
接前一篇C++ ABI之名字改编(以Qt为例),继续看看C++名字改编相关的问题。
问题
MSVC 有一对选项/Zc:wchar_t- 与 /Zc:wchar_t控制wchar_t
于是 wchar_t 可以是 unsigned short 或 __wchar_t(称为原生类型?) 的别名
两个东西混用会怎么样?
首先考虑,会混用么?,是杞人忧天么? 由于 Qt 为 MSVC 提供的二进制包采用的前者/Zc:wchar_t-。考虑:
- 如果你编译自己的Qt程序时,启用了后者,会怎么样?
- 如果Qt程序同时使用了其他的C++库,而且这个库编译时采用了后者。会怎么样?
当然
我们可以自己启用 /Zc:wchar_t 来编译Qt解决这样的问题。本文不考虑这个情况。
wchar_t
- Unicode 4.0标准的5.2节提到:
"The width of wchar_t is compiler-specific and can be as small as 8 bits. Consequently, programs that need to be portable across any C or C++ compilershould not use wchar_t for storing Unicode text. The wchar_t type is intended for storing compiler-defined wide characters, which may be Unicode characters in some compilers."
- C、C++ 标准对这个 wchar_t 不够明确(以至于C++0x、C1x又引入了char16_t/char32_t)
- 各编译器实现 wchar_t 时,是通过typedef定义一个别名。在windows下是 16位整数的别名,在linux等平台下,是 32 位整数的别名。
msvc
MSVC,一直以来,wchar_t与其内部两个类型相关
- unsigned short
__wchar_t
wchar_t 可以是二者之一的别名,通过 /Zc:wchar_t- 与 /Zc:wchar_t进行设置
在MSVC2008之前,默认是前者,从MSVC2008开始,默认改为了后者。
例子
直观一点,直接用msvc生成一个动态库,然后看看它导出的符号:
- 源文件dll.cpp
//dll.cpp
#include <string> __declspec(dllexport) wchar_t * func1()
{
return 0;
} __declspec(dllexport) void func2(wchar_t *)
{
} __declspec(dllexport) std::wstring generateString()
{
return std::wstring();
} __declspec(dllexport) void receiveString(std::wstring str)
{
}
- 分别用两种wchar_t编译上述文件,分别生成out0.dll 和 out1.dll
cl /EHsc /Zc:wchar_t /LD dll.cpp /Feout0.dll
cl /EHsc /Zc:wchar_t- /LD dll.cpp /Feout1.dll
- 而后,用dumpbin查看导出的符号
dumpbin /EXPORTS out0.dll
dumpbin /EXPORTS out1.dll
导出符号
对于原生类型:注意,其中的 _W 代表 wchar_t 即 __wchar_t的类型
?func1@@YAPA_WXZ
?func2@@YAXPA_W@Z
?generateString@@YA?AV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@XZ
?receiveString@@YAXV?$basic_string@_WU?$char_traits@_W@std@@V?$allocator@_W@2@@std@@@Z
对于unsigned short类型:注意其中的 G 代表wchar_t 即 unsigned short的类型
?func1@@YAPAGXZ
?func2@@YAXPAG@Z
?generateString@@YA?AV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@XZ
?receiveString@@YAXV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@@Z
两者改编后的名字不同,如果混用的话:肯定就会因为找不到要找的名字,而出现链接错误了。
对Qt的影响
当混用两种 wchar_t 时,
凡是使用 std::wstring 或 wchar_t 的函数都会受影响,比如
QString QString::fromStdWString(const std::wstring & str)
std::wstring QString::toStdWString () const
int QString::toWCharArray(wchar_t * array) const
QString QString::fromWCharArray(const wchar_t * string, int size = -1)
如何解决呢?解决办法就是这种情况下不使用这些函数(似乎很不讲理哈,有些难以接受?)。
不过http://developer.qt.nokia.com上看到有人给出一个方案,恩,尽管还是如我们刚次所说,方法是在msvc下不使用这些函数,只是似乎不是太难接受了。
/*! 自定义的QString到std::wstring转换的封装 */
std::wstring qToStdWString(const QString &str)
{
#ifdef _MSC_VER
return std::wstring((const wchar_t *)str.utf16());
#else
return str.toStdWString();
#endif
} /*! 自定义的 std::wstring 到 QString 转换的封装 */
QString stdWToQString(const std::wstring &str)
{
#ifdef _MSC_VER
return QString::fromUtf16((const ushort *)str.c_str());
#else
return QString::fromStdWString(str);
#endif
}
参考
http://stackoverflow.com/questions/4667266/c-name-mangling-by-hand
http://labs.qt.nokia.com/2009/08/12/some-thoughts-on-binary-compatibility/
http://developer.qt.nokia.com/wiki/toStdWStringAndBuiltInWchar_SimplifiedChinese
http://blog.csdn.net/dbzhang800/article/details/6707152
----------------------------------------------------------------------
亲测:printf("%d",sizeof(wchar_t));
mingw,VS2005, VS2010下wchar_t都是2个字节(使用默认设置),其中VS2010手动改成wchar_t-后,也是2个字节
但使用QT在linux gcc下测试,wchar_t是4个字节
----------------------------------------------------------------------
解决办法:
const wchar_t *text = L"FooBar";
QString s1 = QString::fromUtf16(reinterpret_cast<const ushort*>(text));
QString s2 = QString::fromWCharArray(text);
qDebug() << "sizeof(wchar_t) = " << sizeof(wchar_t);
qDebug() << "QString::fromUtf16(reinterpret_cast<const ushort*>(text)) =>" << s1;
qDebug() << "QString::fromWCharArray(text) =>" << s2;
https://forum.qt.io/topic/55869/from-wchar_t-to-qstring-qstring-fromutf16-or-qstring-fromwchararray
----------------------------------------------------------------------
QT编译器里也可设置:
qmake.conf 里面设置了:
QMAKE_CFLAGS = -nologo -Zm200 -Zc:wchar_t-
win32 {
QMAKE_CXXFLAGS -= -Zm200
QMAKE_CXXFLAGS += /Zm400
QMAKE_CXXFLAGS += /Zc:wchar_t
}
也可能不要设置 QMAKE_CXXFLAGS
wchar_t是内置还是别名(亲测有效:wchar_t在windows下是16位整数的别名,在linux等平台下是32位整数的别名。MSVC2008开始默认是/Zc:wchar_t)的更多相关文章
- 通过 AppSwitch 禁用 WPF 内置的触摸让 WPF 程序可以处理 Windows 触摸消息
原文:通过 AppSwitch 禁用 WPF 内置的触摸让 WPF 程序可以处理 Windows 触摸消息 WPF 框架自己实现了一套触摸机制,但同一窗口只能支持一套触摸机制,于是这会禁用系统的触摸消 ...
- tomcat内置jdk(tomcat集成jdk)(windows环境)
tomcat内置jdk,步骤: 1.在一个已经安装了jdk或者jre的机器上,拷贝一个jre到tomcat根目录下. 2.编辑tomcat/bin文件夹下的catalina.bat文件,在文件开头加上 ...
- java实现判断一个经纬度坐标是否在一个多边形内(经自己亲测)
1.在高德地图上绘制的多边形:经纬度逗号分隔格式:上面是用来方便存坐标的对象:下面是方法测试:直接复制代码即可运行 public class Point { private Double x; pri ...
- 【亲测】<g++/gcc>CentOS下g++: command not found问题的解决(c++环境安装)
CentOS下g++: command not found问题的解决 2017年02月27日 18:09:06 阅读数:5174 标签: centosgcc 更多 个人分类: 问题分析 版权声明: ...
- 个人亲测,在win10系统下安装多实例mysql8.0详细教程
由于公司的新项目需要导入sql脚本,需要更高版本的mysql数据库,原来的数据库我也不想删除和升级,因此安装了第二个mysql8的实例,废话不多说,步骤如下: 1.下载mysqlGPL版本,我下载的版 ...
- wchar_t内置还是别名?小问题一则(升级公司以前代码遇到的问题)
问题: 原来的2008工程用2010编译后,运行程序出现无法定位程序输入点 *@basic_string@_WU@*和*@basic_string@G@* 解决: 关闭“语言选项”中“将WChar_t ...
- XAF应用开发教程-内置Attribute功能列表
在 XAF 框架,一些用来生成一个业务应用程序的信息是在Attribute中指定.您可以将属性应用到业务类 (或它的成员) 指定验证规则,指定如何对数据进行显示. 设置关系类等.本主题提供了有关在何处 ...
- 与众不同 windows phone (47) - 8.0 其它: 锁屏信息和锁屏背景, 电池状态, 多分辨率, 商店, 内置协议, 快速恢复
[源码下载] 与众不同 windows phone (47) - 8.0 其它: 锁屏信息和锁屏背景, 电池状态, 多分辨率, 商店, 内置协议, 快速恢复 作者:webabcd 介绍与众不同 win ...
- Android 操作手机内置存储卡中的文件
场景:需要读取指定文件的内容,此文件是手动存储到手机内置存储卡中的,且手机上不存在SD卡. 对于android通过activity提供的openFileOutput和openFileInput可以直接 ...
随机推荐
- 破解win7开机密码,又不取消密码
Win7开机密码破解方法 1. 进入pe.(可用系统盘,或者u盘启动) 2.进入c:\windows\system32下 更改magnify.exe和cmd.exe的所有者为administrator ...
- PHP高手干货分享:要大大提高PHP效率
1.用单引号代替双引号来包含字符串,这样做会更快一些.因为PHP会在双 引号包围的字符串中搜寻变量, 单引号则不会,注意:只有echo能这么做,它是一种可以把多个字符串当作参数的”函数”(译注:PHP ...
- eclipse maven SLF4J: Failed to load class org.slf4j.impl.StaticLoggerBinder
现象:运行eclipse maven build,console 有红色日志如下: SLF4J: Failed to load class "org.slf4j.impl.StaticLog ...
- MVC-03 控制器(2)
五.ActionResult解说 ActionResult的继承图: 类型 Controller辅助方法 用途帮助 ContentResult Content 回传一个用户自定义的文字属性 Empty ...
- 帝国cms语句调用
帝国cms系统,灵动标签,有着非常强大的数据调用功能.这里为广大菜鸟站长普及一下. 我们来看这段代码. [e:loop={,,}] <li>·<a target="_bla ...
- 文件的哈希值不在指定的目录文件中。此文件可能已损坏或被篡(Windows10 /Windows8.1)
------------------------------------------Windows10------------------------------------------------ ...
- nginx 重写 rewrite 基础及实例(转)
nginx rewrite 正则表达式匹配 大小写匹配 ~ 为区分大小写匹配 ~* 为不区分大小写匹配 !~和!~*分别为区分大小写不匹配及不区分大小写不匹配 文件及目录匹配 -f和!-f用来判断是否 ...
- perl5 附录一 函数集(未定稿)
附录一 函数集(未定稿) by flamephoenix 一.进程处理函数 1.进程启动函数 2.进程终止函数 3.进程控制函数 4.其它控制函数二.数学函数三.字符串处理函数四.标量转换函数 ...
- android使用全局变量的两种方法
在我们使用android编写程序的时候,少不了想利用全局变量,但是面向对象语言和过程语言区别很大,不再是include就可以的.这里我写了使用全局变量的两种方法: 1.使用applicati ...
- Swift调用Objective C的FrameWork
很多Github的库经过很多年的发展,源码都是OC写的,,所以,用Swift调用OC的库就是开发中难免遇到的的一个问题,本文以AFNetworking为例,讲解如何跨语言调用. 第一步 创建一个空的工 ...