zoukankan      html  css  js  c++  java
  • 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://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

  • 相关阅读:
    To select the file to upload we can use the standard HTML input control of type
    Cascading Menu Script using Javascript Explained
    网站首页head区代码规范
    轻松掌握 Java 泛型
    JDK 5.0 中的泛型类型学习
    如何在firefox下获取下列框选中option的text
    是同步方法还是 synchronized 代码? 详解多线程同步规则
    javascript select option对象总结
    Select的动态取值(Text,value),添加,删除。兼容IE,FireFox
    javascript在ie和firefox下的一些差异
  • 原文地址:https://www.cnblogs.com/findumars/p/5104245.html
Copyright © 2011-2022 走看看