在问这个问题之前,我参考了下面的帖子:
std::string, wstring, u16/32string澄清
Std::u16string, Std::u32string, Std::string, length(), size(),代码点和字符
但是他们不知道我的问题。请看下面的简单代码:
#include<iostream>
#include<string>
using namespace std;
int main ()
{
char16_t x[] = { 'a', 'b', 'c', 0 };
u16string arr = x;
cout << "arr.length = " << arr.length() << endl;
for(auto i : arr)
cout << i << "n";
}
输出为:
arr.length = 3 // a + b + c
97
98
99
考虑到std::u16string
由char16_t
而不是char
组成,那么输出应该是:
arr.length = 2 // ab + c( )
<combining 'a' and 'b'>
99
请原谅我的新手问题。我的要求是弄清楚新的c++ 11字符串的概念。
编辑:
从@Jonathan的回答中,我找到了问题的漏洞。我的观点是如何初始化char16_t
,使arr
的长度变成2
(即ab
, c
)。
仅供参考,下面给出了不同的结果:
char x[] = { 'a', 'b', 'c', 0 };
u16string arr = (char16_t*)x; // probably undefined behavior
输出:arr.length = 3
25185
99
32767
不,您已经创建了一个包含四个元素的数组,第一个元素是'a'
转换为char16_t
,第二个元素是'b'
转换为char16_t
等。
然后从该数组(转换为指针)创建一个u16string
,它读取每个元素直到空终止符。
当你这样做的时候:
char16_t x[] = { 'a', 'b', 'c', 0 };
类似于这样做(不考虑端序):
char x[] = { ' ', 'a', ' ', 'b', ' ', 'c', ' ', ' ' };
每个字符占用两个字节内存。
因此,当您要求u16string
的长度时,每个两个字节被计数为一个字符。毕竟,它们是两个字节(16位)的字符。
您的附加问题是创建字符串而不使用空终止符。
试试这个:
char x[] = { 'a', 'b', 'c', 0 , 0, 0};
u16string arr = (char16_t*)x;
现在第一个字符是{'a', 'b'}
,第二个字符是{'c', 0}
,你也有一个空结束符{0, 0}
。
输出不应该是:
加勒比海盗。长度= 2
//ab + c( )99
。x
的元素是char16_t
,无论您是否为初始化提供char字面值:
#include<iostream>
int main () {
char16_t x[] = { 'a', 'b', 'c', 0 };
std::cout << sizeof(x[0]) << std::endl;
}
输出:2
生活例子
附录, 指问题的编辑
我并不建议将终止符从字符串中强制转换出来。;)
#include<iostream>
#include<string>
int main () {
char x[] = { 'a', 'b', 'c', 0, 0, 0, 0, 0};
std::wstring ws = reinterpret_cast<wchar_t*>(x);
std::u16string u16s = reinterpret_cast<char16_t*>(x);
std::cout << "sizeof(wchar_t): " << sizeof(wchar_t)
<< "twide string length: " << ws.length()
<< std::endl;
std::cout << "sizeof(char16_t): " << sizeof(char16_t)
<< "tu16string length: " << u16s.length()
<< std::endl;
}
生活例子
输出(用g++编译)
sizeof(wchar_t): 4 wide string length: 1
sizeof(char16_t): 2 u16string length: 2
不出所料,不是吗
c++支持以下从8位整数生成16位整数的方法:
char16_t ab = (static_cast<unsigned char>('a') << 8) | 'b';
// (Note: cast to unsigned meant to prevent overflows)