注:本文转载自互联网,感谢作者整理!

 

1. cout



场景1
: 在源文件中定义 const char* str = "中文" 在 VC++ 编译器上,由于Windows环境用 GBK编码,所以字符串 "中文" 被保存为 GBK内码,

编译器也把 str 指向一个包含有 GBK编码的只读内存空间.

用 cout 输出 str 时, 由于中文Windows环境用GBK编码,所以把GBK编码的 str 内容输出到控制台,没问题.



场景2: 在Linux 下编辑一个文件 const char* str = "中文", 由于Linux普遍使用 UTF8 编码,所以在源文件里, "中文" 被保存为 UTF8内码.

然后在Windows中打开这个源文件,由于Windows使用GBK编码,所以VC++ 按照GBK去解释被保存为 UTF8 内码的 "中文", 显示为乱码.



2. wcout



在源文件中定义 const wchar_t* str = L"中文" 在 VC++ 编译器上,由于指定了L,所以字符串 "中文" 被保存为UNICODE内码(UCS2),

编译器也把 str 指向一个包含有 UNICODE 编码的只读内存空间.

用 wcout 输出 str 时, wcout 首先调用 wcstombs() (即根据当前 local 转换, 如果没有设置local,则是经典的C local, 不认识中文)把 str 的内容转换后

交给控制台,结果自然什么都不显示. (调试代码可以知道VC++ 2010 实现是一个字符一个字符输出,调用 wctomb_s)



原理

我们知道 cout 和 wcout 分别是 basic_ostream 的特化版本, 而 basic_ostream 调用 basic_streambuf 实际执行输出动作,针对 wchar_t,

basic_streambuf有专门的特化函数,调用 fputwc 输出一个宽字符,而 fputwc 需要调用 wctomb_s 把宽字符转换后再输出. 我们知道wctomb_s 是依赖 locale 的

由于默认情况下是C locale,所以用中文内码调用 wctomb_s 会失败.



解决办法

设置当前系统的locale 替代默认的 "C" locale, 使 wctomb_s 等函数可以正常工作.

以下3种方法中的任意一种都可以达到目的.



1. C函数设置全局locale

setlocale(LC_ALL, "");



2. C++ 设置全局locale

std::locale::global(std::locale(""));



2. 单独为 wcout 设置一个 locale

std::locale loc("");

std::wcout.imbue(loc);



结论

和Windows API 不同 C++中的各种 w版本的类或者函数并不能提高性能,因为它们都需要用 wc..to..mb 之类的函数转换为ANSI兼容编码然后调用标准库函数.

或者,如果库函数的实现者愿意,针对Windows系统,宽字符的fputwc可以直接调用UNICODE版本的Windows API而不用转换.但是这些都跟C++语言本身没有什么关系.

由于Windows内核是UNICODE的,所以直接用 UNICODE 字符串调用 Windows API会有一点点好处.



C++设计者的出发点: 我不管你用什么字符编码,与C++无关,要输出时:如果是单字节字符或者多字节字符,直接输出;如果是宽字符,则根据local转换为多字节字符,然后再输出.

即使将来UNICODE过时了(假设,假设而已),也不要紧,只要定义好新的local即可.对于C语言也是这样.

Windows设计者的出发点: 统一使用 Unicode 宽字符,解决一切问题

最新文章

  1. Handler系列之创建子线程Handler
  2. Javascript之旅——第一站:从变量说起
  3. Android FM模块学习之三 FM手动调频
  4. html5文章 -- HTML5开发实例-网易微博手机Web App开发过程
  5. android硬件调试之无法识别android设备解决办法
  6. (spring-第14回【IoC基础篇】)国际化信息
  7. Appium对京东App中WebView的处理
  8. I2C总线模拟(郭天祥视屏)
  9. 在树莓派1B上编译安装lnmp服务器
  10. WPF控件中可以用来记录数据用的属性总结
  11. epclise设置tomcat方法(步骤)(菜鸟巧记二)
  12. Ansible实战演练
  13. MongoDB复制集原理、环境配置及基本测试详解
  14. leecode第一百六十九题(求众数)
  15. ubuntu 14.04下使用fcitx时将caps lock映射为ctrl
  16. JavaScript中hasOwnProperty函数
  17. 一次完整的HTTP接口请求过程及针对优化
  18. BZOJ 1834 网络扩容 最大流+最小费用流
  19. maven执行update命令时报org/apache/maven/shared/filtering/MavenFilteringException错误
  20. asp.net 实现pdf、swf等文档的浏览

热门文章

  1. 「每日五分钟,玩转JVM」:指针压缩
  2. 01_垂直居中body中的应用
  3. 当Parallel遇上了DI - Spring并行数据聚合最佳实践
  4. tomcat 介绍及环境搭建
  5. ACM北大暑期课培训第一天
  6. Salesforce LWC学习(十一) port 1717报错的处理
  7. 一个C#开发者重温Java的心路历程
  8. 【转】在NetBeans上搭建Android SDK环境
  9. must appear in the GROUP BY clause or be used in an aggregate function
  10. 读取Core下的appsettings.json的值的时候中文乱码