Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C32R转换为什么编码?_C++_Unicode_C++11 - Fatal编程技术网

C++ C32R转换为什么编码?

C++ C32R转换为什么编码?,c++,unicode,c++11,C++,Unicode,C++11,C Unicode TR()中描述了来自/的C32R和mbrtoc32函数执行UTF-321和“多字节字符”之间的转换 (…)如果s不是空值 指针时,c32r函数确定需要表示的字节数 与c32 (包括任何移位序列),并将多字节字符表示形式存储在 第一个元素由s指向的数组。(……) 什么是“多字节字符表示”?实际上,我对以下程序的行为很感兴趣: #include <cassert> #include <cuchar> #include <string> int

C Unicode TR()中描述了来自
/
C32R
mbrtoc32
函数执行UTF-321和“多字节字符”之间的转换

(…)如果
s
不是空值 指针时,
c32r
函数确定需要表示的字节数 与
c32
(包括任何移位序列),并将多字节字符表示形式存储在 第一个元素由
s
指向的数组。(……)

什么是“多字节字符表示”?实际上,我对以下程序的行为很感兴趣:

#include <cassert>
#include <cuchar>
#include <string>

int main() {
    std::u32string u32 = U"this is a wide string";
    std::string narrow  = "this is a wide string";
    std::string converted(1000, '\0');
    char* ptr = &converted[0];
    std::mbstate_t state {};
    for(auto u : u32) {
        ptr += std::c32rtomb(ptr, u, &state);
    }
    converted.resize(ptr - &converted[0]);
    assert(converted == narrow);
}
#包括
#包括
#包括
int main(){
std::u32string u32=U“这是一个宽字符串”;
std::string shorrow=“这是一个宽字符串”;
std::字符串已转换(1000,“\0”);
char*ptr=&已转换[0];
std::mbstate_t state{};
用于(自动u:u32){
ptr+=std::C32R(ptr、u和状态);
}
已转换。调整大小(ptr-&converted[0]);
断言(转换==窄);
}
其中的断言是否保证保持1



1假设定义了
\u STDC\u UTF\u 32.

问题中链接的TR表示

最多存储
MB\u CUR\u MAX
字节

其定义(在C99中)为

类型为
size\u t
的正整数表达式,它是当前语言环境指定的扩展字符集的多字节字符中的最大字节数


我相信这充分证明了TR的目的是产生当前安装的C语言环境定义的多字节字符:UTF-8用于
en_US.utf8
,GB18030用于
zh_CN.GB18030
,等等。

要保证断言为真,必须确保
c32r()
使用的多字节编码与字符串文本使用的编码相同,至少与字符串中实际使用的字符相同

C99 7.11.1.1/2指定类别为
LC\u CTYPE
setlocale()
影响字符处理函数以及多字节和宽字符函数的行为。我看不到任何明确的确认,其效果是设置使用的多字节和宽字符编码,然而这是目的

因此,
c32r()
使用的多字节编码是来自默认“C”语言环境的多字节编码

C++11 2.14.3/2指定执行编码、宽执行编码、UTF-16和UTF-32用于对应的字符和字符串文本。因此,
std::string shorrow
使用执行编码来表示该字符串

那么这个字符串的“C”语言环境编码与这个字符串的执行编码相同吗

C99 7.11.1.1/3指定“C”语言环境为C翻译提供“最小环境”。这样的环境不仅包括字符集,还包括所使用的特定字符代码。因此,我相信这不仅意味着“C”语言环境必须支持翻译所需的字符(即基本字符集),而且“C”语言环境中的字符必须使用相同的字符代码

字符串文字中的所有字符都是基本字符集的成员,因此将
char32_t
表示转换为
char
“C”语言环境表示必须产生与编译器为
char
字符串文字产生的相同的值序列;这个断言必须成立


我没有看到任何迹象表明,在执行编码和“C”语言环境之间以兼容的方式支持基本字符集之外的任何内容,因此,如果您的字符串文字使用基本字符集之外的任何字符,那么就不能保证断言能够保持。即使规定了存在于执行字符集和“C”语言环境中的扩展字符,我也看不到任何表示相互匹配的要求。

正如我测试的那样,在Linux/MacOSX中,C32R将字符串从UTF-32转换为特定于语言环境的编码。您可以使用nl_langinfo(代码集)获取当前使用的编码

但是,libc默认使用“C”语言环境,它使用ISO-8859-1作为编码。要更改系统环境指定的编码(通常为UTF-8,但也可能是其他编码),请使用setlocale(LC_CTYPE,“”)


但是,在Windows VS2015+中,C32R始终转换为UTF-8。由于vcruntime不支持UTF-8语言环境(仅支持传统的ANSI/OEM语言环境),如果遵循标准,C32R/c16rtomb将与wcrtomb完全相同,根本没有任何用处。

回答不错。需要明确的是:如果他添加了对
setlocale
的调用,即使他的字符串完全在基本字符集内,断言也可能失败?@Nemo如果
setlocale()
是用
“C”
以外的参数调用的,是的。例如,在执行编码与ASCII兼容的系统上,
setlocale(“en_US.EBCDIC”)
(假设这是一个具有明显含义的受支持的区域设置),将导致
c32r()
生成EBCDIC字符串,而
std::string shorrow
将保持ASCII编码。