关于so​​laris(x86)上的std :: basic_string的一些难题

时间:2011-11-14 11:57:35

标签: c++ stl solaris

关于solaris(x86)上的std :: basic_string的一些难题

#include <iostream>
#include <string>
int main()
{
    const wchar_t* s = L"abcdef";
    std::wstring ws(s, s+6);
    for(int i = 0; i < ws.size(); ++i)
    {
        std::cout << ws[i] << std::endl;
    }
    return 0;
}

运行结果是:

97
99
101
0
0
0

为什么不是

97
98
99
100
101
102

代码

#include <iostream>
#include <string>
int main()
{
    const wchar_t* s = L"abcdef";
    std::wstring ws;
    ws.resize(6);       
    for(int i = 0; i < ws.size(); ++i)
    {
        std::cout << (ws[i] = s[i]) << std::endl;
    }
    return 0;
}

可以获得预期的结果。 我使用gcc 3.4.6,构建命令是g++ -fshort-wchar stringtest.cpp。任何一个人都可以表达出来吗?

3 个答案:

答案 0 :(得分:5)

-fshort-wchar的文档读取,

  

-fshort-wchar

     

wchar_t的基础类型覆盖为short unsigned int,而不是目标的默认值。此选项对于构建在WINE下运行的程序非常有用。

     

警告: -fshort-wchar开关导致GCC生成的代码与不使用该开关生成的代码不是二进制兼容的。使用它来符合非默认应用程序二进制接口。

所以看起来这个标志导致了观察到的差异,并且由于语言规范没有讨论这样的标志,所以行为可以分为实现定义或未定义。


作为旁注,在处理宽字符时,您应该使用wcout而不是cout,因为wcout旨在处理宽字符:

  • coutbasic_ostream<char>类型的对象。
  • wcoutbasic_ostream<wchar_t>类型的对象。

在这种情况下,问题不在于你用来打印值的问题,因为你告诉编译器无论如何都要将wchar_t视为short unsigned int

答案 1 :(得分:2)

标准库很可能不会使用--short-wchar进行编译。此标志会更改ABI,但这不会被检测到,因为名称修改不会更改。

答案 2 :(得分:0)

看起来问题是ws[i]给出了错误的结果;当我查看原始内存时,字符串似乎包含预期的数据。令人困惑的是为什么会发生这种情况;据我所知,operator[]只是取消引用指向wchar_t的指针,该指针在其他位置正常工作(例如,在第二个示例中打印s[i])。问题也出现在更新版本的GCC(我试过4.6.1)和Linux上。

您可以使用*(ws.begin() + i)来解决此问题。