<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.0">Jekyll</generator><link href="https://thawk.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://thawk.github.io/" rel="alternate" type="text/html" /><updated>2021-11-24T07:53:13+00:00</updated><id>https://thawk.github.io/feed.xml</id><title type="html">thawk的技术小筑</title><subtitle>C++/并发/Python/Haskell等技术分享</subtitle><author><name>thawk</name></author><entry><title type="html">Unicode与字符编码</title><link href="https://thawk.github.io/%E8%BD%AF%E4%BB%B6/unicode/" rel="alternate" type="text/html" title="Unicode与字符编码" /><published>2021-03-24T12:24:55+00:00</published><updated>2021-03-24T12:24:55+00:00</updated><id>https://thawk.github.io/%E8%BD%AF%E4%BB%B6/unicode</id><content type="html" xml:base="https://thawk.github.io/%E8%BD%AF%E4%BB%B6/unicode/">&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#字符集与字符编码&quot; id=&quot;markdown-toc-字符集与字符编码&quot;&gt;字符集与字符编码&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#基础知识&quot; id=&quot;markdown-toc-基础知识&quot;&gt;基础知识&lt;/a&gt;        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#字符编码的几个概念&quot; id=&quot;markdown-toc-字符编码的几个概念&quot;&gt;字符编码的几个概念&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#代码页code-page&quot; id=&quot;markdown-toc-代码页code-page&quot;&gt;代码页（Code page）&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#字节序endian&quot; id=&quot;markdown-toc-字节序endian&quot;&gt;字节序（Endian）&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#几种常见字符编码&quot; id=&quot;markdown-toc-几种常见字符编码&quot;&gt;几种常见字符编码&lt;/a&gt;        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#ascii&quot; id=&quot;markdown-toc-ascii&quot;&gt;ASCII&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#gbxxxx系列&quot; id=&quot;markdown-toc-gbxxxx系列&quot;&gt;GBXXXX系列&lt;/a&gt;            &lt;ul&gt;
              &lt;li&gt;&lt;a href=&quot;#gb2312&quot; id=&quot;markdown-toc-gb2312&quot;&gt;GB2312&lt;/a&gt;&lt;/li&gt;
              &lt;li&gt;&lt;a href=&quot;#gbk&quot; id=&quot;markdown-toc-gbk&quot;&gt;GBK&lt;/a&gt;&lt;/li&gt;
              &lt;li&gt;&lt;a href=&quot;#gb18030&quot; id=&quot;markdown-toc-gb18030&quot;&gt;GB18030&lt;/a&gt;&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#unicode&quot; id=&quot;markdown-toc-unicode&quot;&gt;Unicode&lt;/a&gt;            &lt;ul&gt;
              &lt;li&gt;&lt;a href=&quot;#unicode的由来&quot; id=&quot;markdown-toc-unicode的由来&quot;&gt;Unicode的由来&lt;/a&gt;&lt;/li&gt;
              &lt;li&gt;&lt;a href=&quot;#ucs与unicode&quot; id=&quot;markdown-toc-ucs与unicode&quot;&gt;UCS与Unicode&lt;/a&gt;&lt;/li&gt;
              &lt;li&gt;&lt;a href=&quot;#ucs-2与ucs-4&quot; id=&quot;markdown-toc-ucs-2与ucs-4&quot;&gt;UCS-2与UCS-4&lt;/a&gt;&lt;/li&gt;
              &lt;li&gt;&lt;a href=&quot;#utf&quot; id=&quot;markdown-toc-utf&quot;&gt;UTF&lt;/a&gt;&lt;/li&gt;
              &lt;li&gt;&lt;a href=&quot;#utf-8-vs-ucs-2&quot; id=&quot;markdown-toc-utf-8-vs-ucs-2&quot;&gt;UTF-8 vs UCS-2&lt;/a&gt;&lt;/li&gt;
            &lt;/ul&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#wide-character宽字符&quot; id=&quot;markdown-toc-wide-character宽字符&quot;&gt;Wide character/宽字符&lt;/a&gt;        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#宽字符-vs-mbcs多字节字符集&quot; id=&quot;markdown-toc-宽字符-vs-mbcs多字节字符集&quot;&gt;宽字符 vs MBCS/多字节字符集&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#宽字符-vs-unicode&quot; id=&quot;markdown-toc-宽字符-vs-unicode&quot;&gt;宽字符 vs Unicode&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#常用操作配置&quot; id=&quot;markdown-toc-常用操作配置&quot;&gt;常用操作、配置&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#unicode字符的录入&quot; id=&quot;markdown-toc-unicode字符的录入&quot;&gt;Unicode字符的录入&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#lc_alllc_lang等不同变量的含义&quot; id=&quot;markdown-toc-lc_alllc_lang等不同变量的含义&quot;&gt;LC_ALL、LC_*、LANG等不同变量的含义&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#设置区域环境的方法&quot; id=&quot;markdown-toc-设置区域环境的方法&quot;&gt;设置区域环境的方法&lt;/a&gt;        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#linux&quot; id=&quot;markdown-toc-linux&quot;&gt;Linux&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#windows&quot; id=&quot;markdown-toc-windows&quot;&gt;Windows&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#putty乱码问题的解决&quot; id=&quot;markdown-toc-putty乱码问题的解决&quot;&gt;putty乱码问题的解决&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#vim的字符编码&quot; id=&quot;markdown-toc-vim的字符编码&quot;&gt;vim的字符编码&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#mysql的utf-8编码&quot; id=&quot;markdown-toc-mysql的utf-8编码&quot;&gt;MySQL的UTF-8编码&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#相关内容&quot; id=&quot;markdown-toc-相关内容&quot;&gt;相关内容&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#几个单词&quot; id=&quot;markdown-toc-几个单词&quot;&gt;几个单词&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#http头中与字符编码有关的部分&quot; id=&quot;markdown-toc-http头中与字符编码有关的部分&quot;&gt;HTTP头中，与字符编码有关的部分&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#参考资料&quot; id=&quot;markdown-toc-参考资料&quot;&gt;参考资料&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;字符集与字符编码&quot;&gt;字符集与字符编码&lt;/h2&gt;

&lt;h3 id=&quot;基础知识&quot;&gt;基础知识&lt;/h3&gt;

&lt;h4 id=&quot;字符编码的几个概念&quot;&gt;字符编码的几个概念&lt;/h4&gt;

&lt;p&gt;计算机中储存的信息都是用二进制数表示的；而我们在屏幕上看到的英文、汉字等字符是二进制数转换之后的结果。&lt;/p&gt;

&lt;p&gt;维基百科中的 &lt;a href=&quot;http://zh.wikipedia.org/wiki/%E5%AD%97%E7%AC%A6%E7%BC%96%E7%A0%81&quot;&gt;“字符编码”&lt;/a&gt; 词条提到下列概念：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;字符集（Character Set）&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;是一个系统支持的所有抽象字符的集合。字符表可以是封闭的，不允许添加新的符号；字符表也可以是开放的，即允许添加新的符号（Unicode和一定程度上代码页是这方面的例子）。&lt;/p&gt;

    &lt;p&gt;如：ASCII字符集中包含的128个字符，GB2312-80字符集中收录了6763个字符。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;编码字符集（CCS:Coded Character Set）&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;就是对字符集中每个字符指定一个数字编码。其中的每个数字叫做&lt;strong&gt;码点&lt;/strong&gt;。&lt;/p&gt;

    &lt;p&gt;例如，在一个给定的字符表中，表示大写拉丁字母“A”的字符被赋予整数65、
字符“B”是66，如此继续下去。多个编码字符集可以表示同样的字符表，例如
ISO-8859-1和IBM的代码页037和500含盖同样的字符集但是将它们映射为不同的代码。&lt;/p&gt;

    &lt;p&gt;UNICODE、UCS-4、UCS-2、GB2312、GB18030都是编码字符集。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;字符编码表（CEF:Character Encoding Form）&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;就是怎么把&lt;strong&gt;编码字符集&lt;/strong&gt;中的整数代码转换成若干固定位数的编码单位（8bit
、16bit、32bit等）。&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;
        &lt;p&gt;最简单的字符编码表就是单纯地选择足够大的单位，以保证编码字符集中的所有数值能够直接编码（一个码点对应一个码值）。如传统非CJK编码（8位），或早期版本的Unicode（16位）。这种情况下，字符编码表就等于编码字符集。&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;随着编码字符集的大小增加，很多系统都使用变长的编码，如UTF-8、UTF-16。&lt;/p&gt;

        &lt;p&gt;UTF-8、UTF-16、UTF-32都对应到相同的编码字符集，但使用的固定位数分别为8位、16位、32位。&lt;/p&gt;

        &lt;p&gt;GB2312、GBK、GB18030等使用的固定位数都为8位。&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;字符编码方案（CES:Character Encoding Scheme）&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;定义如何将整数代码对应到适合基于8位字节数据的文件系统存储或用于网络传输。&lt;/p&gt;

    &lt;p&gt;多数使用Unicode的场合，使用&lt;strong&gt;BOM（Byte Order Mark）&lt;/strong&gt;来指定字节顺序是大端序或者小端序。&lt;/p&gt;

    &lt;p&gt;UTF-16LE、UTF-16BE。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;代码页code-page&quot;&gt;代码页（Code page）&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;代码页&lt;/strong&gt;是字符编码方案的别名，也有人称”内码表”。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;早期的操作系统直接使用BIOS供应的VGA功能来显示字符，只能支持一套字符编码。IBM为每套字符编码指定了一个16位的数字编码。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;目前&lt;strong&gt;代码页&lt;/strong&gt;用得已经不多了，但很多微软程序还使用这些数字来指定编码。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;常见代码页&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;CP437：原始的 IBM PC 代码页&lt;/li&gt;
      &lt;li&gt;CP936：简体中文，微软的CP936通常被视为等同GBK&lt;/li&gt;
      &lt;li&gt;CP950：繁体中文（大五码）&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;字节序endian&quot;&gt;字节序（Endian）&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/unicode/egg.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;“endian”一词来源于乔纳森·斯威夫特的小说格列佛游记。小说中，小人国为水煮蛋该从大的一端（Big-End）剥开还是小的一端（Little-End）剥开而争论，争论的双方分别被称为Big-endians和Little-endians。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;大端序（big-endian）&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/assets/images/unicode/big-endian.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

    &lt;p&gt;最高有效位（MSB, Most Significant Byte）是0x0A 存储在最低的内存地址处。下一个字节0x0B存在后面的地址处。正类似于十六进制字节从左到右的阅读顺序。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;小端序（little-endian）&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;/assets/images/unicode/little-endian.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

    &lt;p&gt;最低有效位（LSB,Least Significant Byte）是0x0D 存储在最低的内存地址处。后面字节依次存在后面的地址处。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;不同处理器体系支持不同的字节序：&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;x86，MOS Technology 6502，Z80，VAX，PDP-11等处理器为Little endian。&lt;/li&gt;
      &lt;li&gt;Motorola 6800，Motorola 68000，PowerPC 970，System/370，SPARC（除V9外）等处理器为Big endian&lt;/li&gt;
      &lt;li&gt;ARM, PowerPC (除PowerPC 970外), DEC Alpha, SPARC V9, MIPS, PA-RISC, IA64的字节序是可配置的。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;网络传输一般采用大端序，也被称之为&lt;strong&gt;网络字节序&lt;/strong&gt;，或&lt;strong&gt;网络序&lt;/strong&gt;。IP协议中定义大端序为网络字节序。&lt;/p&gt;

    &lt;p&gt;NOTE: 伯克利socket API定义了一组转换函数，用于16和32bit整数在网络序和本机字节序之间的转换。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;htonl&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;htons&lt;/code&gt;用于本机序转换到网络序； &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ntohl&lt;/code&gt;，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ntohs&lt;/code&gt;用于网络序转换到本机序。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;几种常见字符编码&quot;&gt;几种常见字符编码&lt;/h3&gt;

&lt;h4 id=&quot;ascii&quot;&gt;ASCII&lt;/h4&gt;

&lt;p&gt;ASCII（American Standard Code for Information Interchange，美国信息交换标准代码）是基于拉丁字母的一套电脑编码系统。它主要用于显示现代英语。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;ASCII字符集&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;主要包括控制字符（回车键、退格、换行键等）；可显示字符（英文大小写字符、阿拉伯数字和西文符号）。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;ASCII编码&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;将ASCII字符集转换为计算机可以接受的数字系统的数的规则。使用7位（bits）表示一个字符，共128字符；但是7位编码的字符集只能支持128个字符，为了表示更多的欧洲常用字符对ASCII进行了扩展，ASCII扩展字符集使用8位（bits）表示一个字符，共256字符。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/unicode/charset-ascii.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;gbxxxx系列&quot;&gt;GBXXXX系列&lt;/h4&gt;

&lt;h5 id=&quot;gb2312&quot;&gt;GB2312&lt;/h5&gt;

&lt;p&gt;GB 2312 或 GB 2312-80 是中国国家标准简体中文字符集，全称《信息交换用汉字编码字符集·基本集》，又称GB0，由中国国家标准总局发布，1981年5月1日实施。&lt;/p&gt;

&lt;p&gt;GB2312共收录6763个汉字，覆盖中国大陆99.75%的使用频率&lt;/p&gt;

&lt;p&gt;GB2312规定：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;一个小于127的字符的意义与原来相同，但两个大于127的字符连在一起时，就表示一个汉字；&lt;/li&gt;
  &lt;li&gt;前面的一个字节（称之为高字节）从0xA1用到 0xF7，后面一个字节（低字节）从0xA1到0xFE，这样就可以组合出大约7000多个简体汉字。&lt;/li&gt;
  &lt;li&gt;数学符号、罗马希腊的 字母、日文的假名们都编进去了，连在ASCII里本来就有的数字、标点、字母都统统重新编了两个字节长的编码，这就是常说的”全角”字符，而原来在127号以下的那些就叫”半角”字符。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/unicode/charset-GB2312.gif&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h5 id=&quot;gbk&quot;&gt;GBK&lt;/h5&gt;

&lt;p&gt;GBK即&lt;strong&gt;汉字内码扩展规范&lt;/strong&gt;。&lt;/p&gt;

&lt;p&gt;1993年，Unicode 1.1版本推出，收录中国大陆、台湾、日本及韩国通用字符集的汉字，总共有20,902个。中国大陆订定了等同于Unicode 1.1版本的“GB 13000.1-93”“信息技术通用多八位编码字符集（UCS）第一部分：体系结构与基本多文种平面”。&lt;/p&gt;

&lt;p&gt;由于GB 2312-80只收录6763个汉字，有不少汉字并未有收录在内，于是厂商微软利用GB 2312-80未使用的编码空间，收录GB 13000.1-93全部字符制定了GBK编码。&lt;/p&gt;

&lt;p&gt;最早实现于Windows 95简体中文版。虽然GBK收录GB 13000.1-93的全部字符，但编码方式并不相同。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;GBK自身并非国家标准，只是曾由国家技术监督局标准化司、电子工业部科技与质量监督司公布为“技术规范指导性文件”。原始GB13000一直未被业界采用，后续国家标准GB18030技术上兼容GBK而非GB13000。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;table&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;GBK的第二字节使用了0x40至0x7E的范围，由于这个范围内包含一些特殊字符（如“&lt;/td&gt;
          &lt;td&gt;”、“\”），因此可能会被一些程序误处理。由于保持与GBK的兼容性，GB18030也有同样的问题。&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id=&quot;gb18030&quot;&gt;GB18030&lt;/h5&gt;

&lt;p&gt;GB 18030，最新版本为GB 18030-2005，其全称为中华人民共和国国家标准GB 18030-2005《信息技术 中文编码字符集》，与GB 2312-1980完全兼容，与GBK基本兼容，支持GB 13000及Unicode的全部统一汉字，共收录汉字70244个。&lt;/p&gt;

&lt;p&gt;GB18030有以下特点：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;与 UTF-8 相同，采用多字节编码，每个字可以由1个、2个或4个字节组成。
    &lt;ul&gt;
      &lt;li&gt;单字节部分使用0x00至0x7F码位。&lt;/li&gt;
      &lt;li&gt;双字节部分采用两个字节表示一个字符，其首字节码位从0x81至0xFE，尾字节码位分别是0x40至0x7E和0x80至0xFE。&lt;/li&gt;
      &lt;li&gt;四字节部分，第一个字节的编码为0x81至0xFE；第二个字节的编码范围为0x30至0x39；第三个字节编码范围为0x81至0xFE；第四个字节编码范围为0x30至0x39。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;编码空间庞大，最多可定义161万个字符。（能表示所有Unicode码点，其映射关系一部分要通过查表得出，一部分可以通过算法求出）&lt;/li&gt;
  &lt;li&gt;支持中国国内少数民族的文字，不需要动用造字区。&lt;/li&gt;
  &lt;li&gt;汉字收录范围包含繁体汉字以及日韩汉字&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;unicode&quot;&gt;Unicode&lt;/h4&gt;

&lt;h5 id=&quot;unicode的由来&quot;&gt;Unicode的由来&lt;/h5&gt;

&lt;p&gt;Unicode（统一码、万国码、单一码、标准万国码）是计算机科学领域里的一项业界标准，用以统一地呈现和处理世界上大部分的文字系统，并为其编码。&lt;/p&gt;

&lt;p&gt;传统字符编码方案的主要缺陷：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;由于不同的系统采用不同的字符编码，导致多个系统间难以进行数据交换。&lt;/li&gt;
  &lt;li&gt;由于不同字符编码方案可能使用相同的编码区间，同一个数值在不同编码方案中有不同的含义，因此电脑系统难以同时支持多语种。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;为解决传统字符编码的问题，制定了一个国际标准，叫做Unicode。Unicode为每个字符提供了唯一的特定数值，不论在什么平台上、不论在什么软件中，也不论什么语言。也就是说，它世界上使用的所有字符都列出来，并给每一个字符一个唯一特定数值。&lt;/p&gt;

&lt;p&gt;Unicode一般使用U+hhhh的方式表示。如U+6731就是“朱”字。&lt;/p&gt;

&lt;h5 id=&quot;ucs与unicode&quot;&gt;UCS与Unicode&lt;/h5&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;通用字符集（Universal Character Set，UCS）是由ISO制定的ISO 10646（或称ISO/IEC 10646）标准所定义的标准字符集。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Unicode则是由统一码联盟（英语：The Unicode Consortium）（主要由来自多个国家政府和各大软件商的代表参与）制定。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;ISO 10646和Unicode最初是不同的标准：&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;
        &lt;p&gt;ISO10646定义了128组(groups)&lt;em&gt;256平面( planes)&lt;/em&gt;256行(rows)*256字位 (cells)=2^31^个码点，实际上排除了一些不可用的控制字符后，可用
79,477,248个码点。&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;Unicode只使用16位，65536个码点。&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;业界认为ISO 10646太复杂，占用太多空间（4字节），因而不愿意接受。标准 制订者也认识到这点，因此将基本字符平面（U+0000至U+FFFF）保持与Unicode（16 bit）一致。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;随着应用的发展，Unicode的16 bit也不够用，因此Unicode从v2.0开始扩展为包含17个平面，1,112,064个码点。对应UCS U+00000000 ~ U+00100000区间。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;ISO 10646和Unicode两个项目独立地公布各自的标准，但双方都同意保持两者标准的码表兼容，并紧密地共同调整任何未来的扩展。在使用时，基本可以把UCS和Unicode视为相同的概念。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;平面&lt;/th&gt;
      &lt;th&gt;始末字符值&lt;/th&gt;
      &lt;th&gt;中文名称&lt;/th&gt;
      &lt;th&gt;英文名称&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;0号平面&lt;/td&gt;
      &lt;td&gt;U+0000 - U+FFFF&lt;/td&gt;
      &lt;td&gt;基本多文种平面&lt;/td&gt;
      &lt;td&gt;Basic Multilingual Plane，简称BMP&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;1号平面&lt;/td&gt;
      &lt;td&gt;U+10000 - U+1FFFF&lt;/td&gt;
      &lt;td&gt;多文种补充平面&lt;/td&gt;
      &lt;td&gt;Supplementary Multilingual Plane，简称SMP&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2号平面&lt;/td&gt;
      &lt;td&gt;U+20000 - U+2FFFF&lt;/td&gt;
      &lt;td&gt;表意文字补充平面&lt;/td&gt;
      &lt;td&gt;Supplementary Ideographic Plane，简称SIP&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;3号平面&lt;/td&gt;
      &lt;td&gt;U+30000 - U+3FFFF&lt;/td&gt;
      &lt;td&gt;表意文字第三平面&lt;/td&gt;
      &lt;td&gt;Tertiary Ideographic Plane，简称TIP&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;4号至13号平面&lt;/td&gt;
      &lt;td&gt;U+40000 - U+DFFFF&lt;/td&gt;
      &lt;td&gt;（尚未使用）&lt;/td&gt;
      &lt;td&gt; &lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;14号平面&lt;/td&gt;
      &lt;td&gt;U+E0000 - U+EFFFF&lt;/td&gt;
      &lt;td&gt;特别用途补充平面&lt;/td&gt;
      &lt;td&gt;Supplementary Special-purpose Plane，简称SSP&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;15号平面&lt;/td&gt;
      &lt;td&gt;U+F0000 - U+FFFFF&lt;/td&gt;
      &lt;td&gt;保留作为私人使用区（A区）&lt;/td&gt;
      &lt;td&gt;Private Use Area-A，简称PUA-A&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;16号平面&lt;/td&gt;
      &lt;td&gt;U+100000 - U+10FFFF&lt;/td&gt;
      &lt;td&gt;保留作为私人使用区（B区）&lt;/td&gt;
      &lt;td&gt;Private Use Area-B，简称PUA-B&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h5 id=&quot;ucs-2与ucs-4&quot;&gt;UCS-2与UCS-4&lt;/h5&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;ISO 10646定义了三种字符编码方式：&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;
        &lt;p&gt;&lt;strong&gt;UCS-4&lt;/strong&gt;，每个字符使用4个字节，可以编码所有UCS字符。&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;&lt;strong&gt;UCS-2&lt;/strong&gt;，每个字符使用2个字节，只可以编码0号平面的字符。编码从
U+0000至U+FFFF。&lt;/p&gt;

        &lt;p&gt;&lt;strong&gt;Unicode&lt;/strong&gt;的早期版本也只支持2个字节，与&lt;strong&gt;UCS-2&lt;/strong&gt;一致。&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;&lt;strong&gt;UTF-1&lt;/strong&gt;，每个字符使用1~5字节的变长编码。基本上被&lt;strong&gt;UTF-8&lt;/strong&gt;取代。&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id=&quot;utf&quot;&gt;UTF&lt;/h5&gt;

&lt;p&gt;Unicode只是一种编码字符集（CCS:Coded Character Set），定义字符与编码之间的关系。但在实际应用中，还需要定义怎样传输Unicode编码，这就是Unicode 转换格式（Unicode Transformation Format，简称为&lt;strong&gt;UTF&lt;/strong&gt;）。&lt;/p&gt;

&lt;p&gt;目前常用的Unicode实现方式：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;UTF-8&lt;/strong&gt;：变长编码，每个字符使用一到六个字节。基本7位ASCII字符仍用7位编码表示，占用一个字节（首位补0），汉字等大部分常用字使用3个字节（首字节为Ex）。&lt;/p&gt;

    &lt;p&gt;虽然UTF-8最长可以支持6个字节，但2003年11月UTF-8被RFC 3629重新规范，只能使用原来Unicode定义的区域，U+0000到U+10FFFF，最长&lt;strong&gt;4个字节&lt;/strong&gt;，最大的字符是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;F4 8F BF BF&lt;/code&gt;。&lt;/p&gt;

    &lt;table&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th&gt;Unicode码点&lt;/th&gt;
          &lt;th&gt;UTF-8编码&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;U-00000000 – U-0000007F&lt;/td&gt;
          &lt;td&gt;0xxxxxxx&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;U-00000080 – U-000007FF&lt;/td&gt;
          &lt;td&gt;110xxxxx 10xxxxxx&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;U-00000800 – U-0000FFFF&lt;/td&gt;
          &lt;td&gt;1110xxxx 10xxxxxx 10xxxxxx&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;U-00010000 – U-001FFFFF&lt;/td&gt;
          &lt;td&gt;11110xxx 10xxxxxx 10xxxxxx 10xxxxxx&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;U-00200000 – U-03FFFFFF&lt;/td&gt;
          &lt;td&gt;111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;U-04000000 – U-7FFFFFFF&lt;/td&gt;
          &lt;td&gt;1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;UTF-16&lt;/strong&gt;：变长编码，对于BMP平面内的字符使用两个字节，对于其它平面的字符使用四个字节。根据字节顺序，又可以分为UTF-16 LE和UTF-16 BE。Windows和Linux中，默认为UTF-16 LE。&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;UTF-16是UCS-2的超集。
        &lt;ul&gt;
          &lt;li&gt;UCS-2只能使用2字节编码。&lt;/li&gt;
          &lt;li&gt;UTF-16是2字节或4字节的变长编码。其2字节部分兼容UCS-2。&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;通常如果一个软件声称能支持UCS-2，往往暗示其不能支持UTF-16 中超过2字节的部分。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;NOTE: 在Windows记事本程序中，“另存为”对话框可以选择四种编码，ANSI为非Unicode编码（对应于当前系统内码，如GBK），其余三种为“Unicode”（对应UTF-16 LE）、“Unicode big endian”（对应UTF-16 BE）和“UTF-8”&lt;/p&gt;

&lt;h5 id=&quot;utf-8-vs-ucs-2&quot;&gt;UTF-8 vs UCS-2&lt;/h5&gt;

&lt;p&gt;UTF-8&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;优点&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;完美兼容ASCII（0x00到0x7F）。&lt;/li&gt;
      &lt;li&gt;Linux的内核是UTF-8的，意味着在Linux下使用UTF-8有得天独厚的优势。而且不仅仅是Linux，大量的开源计划（由于大部分开源计划都是围绕着Linux走的），包括网页，XML等也都是原生UTF-8的，可参考源程序范例更多。&lt;/li&gt;
      &lt;li&gt;单字节编码，从一个字节到四个字节，不用考虑大头小头的字节序问题。&lt;/li&gt;
      &lt;li&gt;自同步，可以轻易识别字符的开始及字符占用的字节数。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;缺点&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;大量的组合字符（即用两个以上字节来表示一个字符），使得字符串的处理很不方便。&lt;/li&gt;
      &lt;li&gt;以非ASCII字符为主的数据在存储时，占用空间较大。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;UCS-2&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;优点
    &lt;ul&gt;
      &lt;li&gt;统一定长编码，两个字节对应一个字符，对于字符串的处理非常方便。大量的宽字节C/C++函数都可以直接使用。&lt;/li&gt;
      &lt;li&gt;Windows的内核是UTF-16的，由于UCS-2是UTF-16的一个子集，所以在Windows下使用UCS-2，有得天独厚的优势。另外，从资料上看，使用UTF-16/UCS-2的操作系统阵营比使用UTF-8的更加庞大。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;缺点
    &lt;ul&gt;
      &lt;li&gt;UCS-2只能表示Unicode的一个子集，有部分字符不在UCS-2表示范围内。&lt;/li&gt;
      &lt;li&gt;在 Unix 下使用 UCS-2 (或 UCS-4) 会导致非常严重的问题。用这些编码的字符串会包含一些特殊的字符，比如’\0’或’/’，它们在文件名和其他 C 库函数参数里都有特别的含义. 另外, 大多数使用 ASCII 文件的 UNIX 下的工具, 如果不进行重大修改是无法读取 16 位的字符的. 基于这些原因, 在文件名, 文本文件, 环境变量等地方, UCS-2 不适合作为 Unicode 的外部编码。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;wide-character宽字符&quot;&gt;Wide character/宽字符&lt;/h3&gt;

&lt;p&gt;宽字符（Wide character）是程序设计的术语。它是一个含糊的术语，用以表示比8位字符还宽的数据类型。&lt;/p&gt;

&lt;p&gt;C/C++中，以&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;wchar_t&lt;/code&gt;类型表示宽字符。&lt;/p&gt;

&lt;h4 id=&quot;宽字符-vs-mbcs多字节字符集&quot;&gt;宽字符 vs MBCS/多字节字符集&lt;/h4&gt;

&lt;p&gt;C标准中，&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;MBCS指的是使用固定或可变数量的字节来表示单个字符。一个字符占用多个逻辑单元。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;宽字符指的是在&lt;strong&gt;程序运行过程中&lt;/strong&gt;通过&lt;strong&gt;一个&lt;/strong&gt;对象来表达&lt;strong&gt;一个&lt;/strong&gt;字符。一个字符占用一个逻辑单元。&lt;/p&gt;

    &lt;p&gt;(Wide characters) which are run-time representations of characters in single objects&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;宽字符-vs-unicode&quot;&gt;宽字符 vs Unicode&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;宽字符只表示不小于8位的字符（在C/C++标准中，只要求wchar_t的大小不小于8位），并没有规定使用何种字符编码。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;在很多程序设计语言中，宽字符中存放的是Unicode数值。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;由于受以前使用UCS-2的影响，Win 32/Win 64 API以及Java/.Net Framework都把宽字符的大小定义为16位，采用UTF-16编码。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;类Unix系统一般把宽字符的大小定义为32位，采用UTF-32编码。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;常用操作配置&quot;&gt;常用操作、配置&lt;/h2&gt;

&lt;h3 id=&quot;unicode字符的录入&quot;&gt;Unicode字符的录入&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;很多输入法都支持Unicode字符&lt;/li&gt;
  &lt;li&gt;通常可以通过字符映射表之类的程序，直接从屏幕上选择所需的字符
    &lt;ul&gt;
      &lt;li&gt;Windows下在开始－运行中，输入charmap即可打开“字符映射表”程序&lt;/li&gt;
      &lt;li&gt;Mac OS X/GNOME/KDE都有相应的工具程序&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Windows的RTF控件（包括在写字版程序及Word中），有两种输入Unicode字符的方式：
    &lt;ul&gt;
      &lt;li&gt;输入字符对应的4位16进制Unicode编码，再按&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alt-X&lt;/code&gt;&lt;/li&gt;
      &lt;li&gt;按住&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alt&lt;/code&gt;键不放，在小键盘上输入字符对应的10进制编码，放开&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Alt&lt;/code&gt;键&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;在Vim中，先输入Ctrl-V，然后按字母u，再输入4位16进制Unicode字符编码&lt;/li&gt;
  &lt;li&gt;在GTK+程序，如GNOME中，可以先按&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Ctrl-Shift-u&lt;/code&gt;，放开，再输入4位16进制Unicode编码，再按&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Enter&lt;/code&gt;键&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;lc_alllc_lang等不同变量的含义&quot;&gt;LC_ALL、LC_*、LANG等不同变量的含义&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;POSIX系统中有12个LC_&lt;em&gt;变量，分别设置语言环境的不同方面，还可以设置 LC_ALL，该设置将覆盖这12项LC_&lt;/em&gt;设置。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;变量优先级的关系：LC_ALL &amp;gt; LC_* &amp;gt;LANG&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;变量含义&lt;/p&gt;

    &lt;table&gt;
      &lt;thead&gt;
        &lt;tr&gt;
          &lt;th&gt;编码&lt;/th&gt;
          &lt;th&gt;含义&lt;/th&gt;
        &lt;/tr&gt;
      &lt;/thead&gt;
      &lt;tbody&gt;
        &lt;tr&gt;
          &lt;td&gt;zh_CN.UTF-8&lt;/td&gt;
          &lt;td&gt;简体中文，使用UTF-8编码&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;zh_CN.GB18030&lt;/td&gt;
          &lt;td&gt;简体中文，使用GB18030编码&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;en_US.UTF-8&lt;/td&gt;
          &lt;td&gt;美国英语，使用UTF-8编码&lt;/td&gt;
        &lt;/tr&gt;
        &lt;tr&gt;
          &lt;td&gt;en_US.GB18030&lt;/td&gt;
          &lt;td&gt;美国英语，使用GB18030编码&lt;/td&gt;
        &lt;/tr&gt;
      &lt;/tbody&gt;
    &lt;/table&gt;

    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;语言代码&lt;/strong&gt;_&lt;strong&gt;国家代码&lt;/strong&gt;.&lt;strong&gt;编码&lt;/strong&gt;&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;语言代码&lt;/strong&gt;和&lt;strong&gt;国家代码&lt;/strong&gt;决定软件界面使用什么语言（如&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ls --help&lt;/code&gt;时，显示中文帮助还是英文帮助信息）&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;编码&lt;/strong&gt;决定各种字符使用何种字符编码来表示&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;12个LC_*变量的具体含义如下：&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;LC_CTYPE&lt;/td&gt;
      &lt;td&gt;语言符号及其分类。决定系统的内码。&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;LC_NUMERIC&lt;/td&gt;
      &lt;td&gt;数字&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;LC_COLLATE&lt;/td&gt;
      &lt;td&gt;比较和排序习惯&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;LC_TIME&lt;/td&gt;
      &lt;td&gt;时间显示格式&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;LC_MONETARY&lt;/td&gt;
      &lt;td&gt;货币单位&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;LC_MESSAGES&lt;/td&gt;
      &lt;td&gt;信息。主要是提示信息,错误信息,状态信息,标题,标签,按钮和菜单等&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;LC_NAME&lt;/td&gt;
      &lt;td&gt;姓名书写方式&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;LC_ADDRESS&lt;/td&gt;
      &lt;td&gt;地址书写方式&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;LC_TELEPHONE&lt;/td&gt;
      &lt;td&gt;电话号码书写方式&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;LC_MEASUREMENT&lt;/td&gt;
      &lt;td&gt;度量衡表达方式&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;LC_PAPER&lt;/td&gt;
      &lt;td&gt;默认纸张尺寸大小&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;LC_IDENTIFICATION&lt;/td&gt;
      &lt;td&gt;对locale自身包含信息的概述&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&quot;设置区域环境的方法&quot;&gt;设置区域环境的方法&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/unicode/linux_locale.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;linux&quot;&gt;Linux&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;locale&lt;/code&gt;命令可以查看上述LC_*，LANG等变量的状态&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;设置整个环境为简体中文UTF-8环境：
    &lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LC_ALL&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;zh_CN.UTF-8
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;把内码设置UTF-8，其它环境保持不变：
    &lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;LC_CTYPE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;zh_CN.UTF-8
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/unicode/win7_locale.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;h4 id=&quot;windows&quot;&gt;Windows&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;可以通过“控制面板”——“区域和语言”——“管理”——“更改系统区域设置”进行修改&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;putty乱码问题的解决&quot;&gt;putty乱码问题的解决&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;/assets/images/unicode/putty-translation-setting.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;putty配置中，Window-Translation-Remote character set的设置要与服务器的设置一致。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;vim的字符编码&quot;&gt;vim的字符编码&lt;/h3&gt;

&lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;fileencodings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;utf&lt;span class=&quot;m&quot;&gt;-8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;ucs&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;bom&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;gb18030&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;gbk&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;gb2312&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;cp936
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;mysql的utf-8编码&quot;&gt;MySQL的UTF-8编码&lt;/h3&gt;

&lt;p&gt;MySQL中，由于历史原因，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;utf8&lt;/code&gt;是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;utf8mb3&lt;/code&gt;的别名，只支持BMP平面，3字节的UTF-8字符。后来版本的MySQL中，引入了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;utf8mb4&lt;/code&gt;，支持完整的Unicode字符集。&lt;/p&gt;

&lt;p&gt;MySQL文档（&lt;a href=&quot;https://dev.mysql.com/doc/refman/8.0/en/charset-unicode-utf8.html&quot;&gt;MySQL: MySQL 8.0 Reference Manual :: 10.9.3 The utf8 Character Set (Alias for utf8mb3)&lt;/a&gt;）中明确提出应该使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;utf8mb4&lt;/code&gt;而不是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;utf8&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;utf8mb3&lt;/code&gt;，并指出以后&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;utf8&lt;/code&gt;会被改为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;utf8mb4&lt;/code&gt;的别名：&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The utf8mb3 character set is deprecated and you should expect it to be removed in a future MySQL release. Please use utf8mb4 instead. Although utf8 is currently an alias for utf8mb3, at some point utf8 is expected to become a reference to utf8mb4. To avoid ambiguity about the meaning of utf8, consider specifying utf8mb4 explicitly for character set references instead of utf8.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2 id=&quot;相关内容&quot;&gt;相关内容&lt;/h2&gt;

&lt;h3 id=&quot;几个单词&quot;&gt;几个单词&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;*i18n&lt;/em&gt;: Internationalization，国际化。指在设计软件，将软件与特定语言及地区脱钩的过程。当软件被移植到不同的语言及地区时，软件本身不用做内部工程上的改变或修正。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;L10n&lt;/em&gt;: Localization，本地化。指当移植软件时，加上与特定区域设置有关的信息和翻译文件的过程。使用大写的L以利区分i18n中的i。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;em&gt;g11n&lt;/em&gt;: Globalization，全球化。微软及IBM等企业中，会使用全球化一词来作为国际化和本地化两者的合称&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;http头中与字符编码有关的部分&quot;&gt;HTTP头中，与字符编码有关的部分&lt;/h3&gt;

&lt;p&gt;在HTTP中，与字符集和字符编码相关的消息头是Accept-Charset/Content-Type，另外还有一些容易混淆的消息头：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Accept-Charset：浏览器申明自己接收的字符集，这就是本文前面介绍的各种字符集和字符编码，如gb2312，utf-8（通常我们说Charset包括了相应的字符编码方案）；&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Accept-Encoding：浏览器申明自己接收的编码方法，通常指定压缩方法，是否支持压缩，支持什么压缩方法（gzip，deflate），（注意：这不是只字符编码）；&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Accept-Language：浏览器申明自己接收的语言。语言跟字符集的区别：中文是语言，中文有多种字符集，比如big5，gb2312，gbk等等；&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Content-Type：WEB服务器告诉浏览器自己响应的对象的类型和字符集。例如：Content-Type: text/html; charset=’gb2312’&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Content-Encoding：WEB服务器表明自己使用了什么压缩方法（gzip，deflate）压缩响应中的对象。例如：Content-Encoding：gzip&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Content-Language：WEB服务器告诉浏览器自己响应的对象的语言。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;参考资料&quot;&gt;参考资料&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;字符编码: http://zh.wikipedia.org/wiki/%E5%AD%97%E7%AC%A6%E7%BC%96%E7%A0%81&lt;/li&gt;
  &lt;li&gt;Unicode: http://zh.wikipedia.org/wiki/Unicode&lt;/li&gt;
  &lt;li&gt;Universal Character Set: http://en.wikipedia.org/wiki/Universal_Character_Set&lt;/li&gt;
  &lt;li&gt;UTF-8: https://zh.wikipedia.org/wiki/UTF-8&lt;/li&gt;
  &lt;li&gt;UTF-16: http://zh.wikipedia.org/wiki/UCS-2&lt;/li&gt;
  &lt;li&gt;Unicode字符平面映射: http://zh.wikipedia.org/wiki/Unicode%E5%AD%97%E7%AC%A6%E5%B9%B3%E9%9D%A2%E6%98%A0%E5%B0%84&lt;/li&gt;
  &lt;li&gt;GBK: http://zh.wikipedia.org/wiki/GBK&lt;/li&gt;
  &lt;li&gt;代码页: http://zh.wikipedia.org/wiki/%E4%BB%A3%E7%A0%81%E9%A1%B5&lt;/li&gt;
  &lt;li&gt;Wide character: http://en.wikipedia.org/wiki/Wide_character&lt;/li&gt;
  &lt;li&gt;区域设置: http://zh.wikipedia.org/wiki/%E5%8C%BA%E5%9F%9F%E8%AE%BE%E7%BD%AE&lt;/li&gt;
  &lt;li&gt;字符集和字符编码（Charset &amp;amp; Encoding）: http://www.cnblogs.com/skynet/archive/2011/05/03/2035105.html&lt;/li&gt;
  &lt;li&gt;UTF-8 and Unicode FAQ: http://www.linuxforum.net/books/UTF-8-Unicode.html&lt;/li&gt;
  &lt;li&gt;C++的中英文字符串表示(string,wstring): http://www.cnblogs.com/xiaoyz/archive/2008/10/11/1308860.html&lt;/li&gt;
  &lt;li&gt;彻底解密C++宽字符: http://www.cppblog.com/lf426/archive/2010/06/25/118707.html&lt;/li&gt;
  &lt;li&gt;UCS-2与UTF8之间的选择: http://blog.csdn.net/vagrxie/archive/2009/03/01/3947195.aspx&lt;/li&gt;
&lt;/ul&gt;</content><author><name>thawk</name></author><category term="软件" /><category term="unicode" /><summary type="html"></summary></entry><entry><title type="html">国标GB/T 1.1-2009中对助动词的使用规范</title><link href="https://thawk.github.io/%E6%9D%82%E8%B0%88/gbt1.1-2009-requirement-levels/" rel="alternate" type="text/html" title="国标GB/T 1.1-2009中对助动词的使用规范" /><published>2019-09-05T08:45:47+00:00</published><updated>2019-09-05T08:45:47+00:00</updated><id>https://thawk.github.io/%E6%9D%82%E8%B0%88/gbt1.1-2009-requirement-levels</id><content type="html" xml:base="https://thawk.github.io/%E6%9D%82%E8%B0%88/gbt1.1-2009-requirement-levels/">&lt;p&gt;之前在&lt;a href=&quot;/%E6%9D%82%E8%B0%88/rfc-2119-requirement-levels/&quot;&gt;RFC 2119 文档中定义要求级别的关键字&lt;/a&gt;中提到了&lt;a href=&quot;https://tools.ietf.org/html/rfc2119&quot;&gt;RFC 2119&lt;/a&gt;对要求级别的标准术语，最近找到国标中类似的内容。&lt;/p&gt;

&lt;p&gt;来源：《GB/T 1.1-2009 标准化工作导则 第1部分：标准的结构和编写》&lt;/p&gt;

&lt;h2 id=&quot;标准要求&quot;&gt;标准要求&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;要求&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;
        &lt;p&gt;用途&lt;/p&gt;

        &lt;ul&gt;
          &lt;li&gt;用于表示声明符合标准需要满足的要求&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;应&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;不应&lt;/code&gt;&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;特殊情况下使用的等效表述&lt;/p&gt;

        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;应该&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;只准许&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;不得&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;不准许&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;备注&lt;/p&gt;

        &lt;ul&gt;
          &lt;li&gt;不使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;必须&lt;/code&gt;作为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;应&lt;/code&gt;的替代词，以避免将某标准的要求和外部的法定责任相混淆&lt;/li&gt;
          &lt;li&gt;不使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;不可&lt;/code&gt;代替&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;不应&lt;/code&gt;表示禁止&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;推荐&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;
        &lt;p&gt;用途&lt;/p&gt;

        &lt;ul&gt;
          &lt;li&gt;表示在集中可能性中推荐特别适合的一种，不提及也不排除其他可能型&lt;/li&gt;
          &lt;li&gt;表示某个行动步骤是首选的但未必是所要求的&lt;/li&gt;
          &lt;li&gt;以否定形式表示不赞成但也不禁止某种可能性或行动步骤&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;宜&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;不宜&lt;/code&gt;&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;特殊情况下使用的等效表述&lt;/p&gt;

        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;推荐&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;建议&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;不推荐&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;不建议&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;允许&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;
        &lt;p&gt;用途&lt;/p&gt;

        &lt;ul&gt;
          &lt;li&gt;表示在标准的界限内所允许的行动步骤&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;可&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;不必&lt;/code&gt;&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;特殊情况下使用的等效表述&lt;/p&gt;

        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;可以&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;允许&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;无须&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;不需要&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;备注&lt;/p&gt;

        &lt;ul&gt;
          &lt;li&gt;在这种情况下，不使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;可能&lt;/code&gt;或&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;不可能&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;在这种情况下，不使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;能&lt;/code&gt;代替&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;可&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;能力和可能性&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;
        &lt;p&gt;用途&lt;/p&gt;

        &lt;ul&gt;
          &lt;li&gt;用于陈述由材料、生理的或某种原因导致的能力或可能性&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;能&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;不能&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;可能&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;不可能&lt;/code&gt;&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;特殊情况下使用的等效表述&lt;/p&gt;

        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;能够&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;不能够&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;有可能&lt;/code&gt;&lt;/li&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;没有可能&lt;/code&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;备注&lt;/p&gt;

        &lt;ul&gt;
          &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;能&lt;/code&gt;指主、客观原因导致的能力，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;可能&lt;/code&gt;则指主、客观原因导致的可能性&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;与rfc-2119的对比&quot;&gt;与RFC 2119的对比&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;用途&lt;/th&gt;
      &lt;th&gt;GBT/1.1-2009&lt;/th&gt;
      &lt;th&gt;RFC 2119&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;要求&lt;/td&gt;
      &lt;td&gt;应 / 应该 / 只准许&lt;/td&gt;
      &lt;td&gt;MUST / REQUIRED / SHALL&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;要求&lt;/td&gt;
      &lt;td&gt;不应 / 不得 / 不准许&lt;/td&gt;
      &lt;td&gt;MUST NOT / SHALL NOT&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;推荐&lt;/td&gt;
      &lt;td&gt;宜 / 推荐 / 建议&lt;/td&gt;
      &lt;td&gt;SHOULD / RECOMMENDED&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;推荐&lt;/td&gt;
      &lt;td&gt;不宜 / 不推荐 / 不建议&lt;/td&gt;
      &lt;td&gt;SHOULD NOT / NOT RECOMMENDED&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;允许&lt;/td&gt;
      &lt;td&gt;可 / 可以 / 允许&lt;/td&gt;
      &lt;td&gt;MAY / OPTIONAL&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;允许&lt;/td&gt;
      &lt;td&gt;不必 / 无须 / 不需要&lt;/td&gt;
      &lt;td&gt;无&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;能力和可能性&lt;/td&gt;
      &lt;td&gt;能 / 能够 / 可能 / 有可能&lt;/td&gt;
      &lt;td&gt;无&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;能力和可能性&lt;/td&gt;
      &lt;td&gt;不能 / 不能够 / 不可能 / 没有可能&lt;/td&gt;
      &lt;td&gt;无&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;</content><author><name>thawk</name></author><category term="杂谈" /><category term="规范" /><summary type="html">之前在RFC 2119 文档中定义要求级别的关键字中提到了RFC 2119对要求级别的标准术语，最近找到国标中类似的内容。</summary></entry><entry><title type="html">关于Bash的内置getopts命令</title><link href="https://thawk.github.io/%E8%BD%AF%E4%BB%B6/bash-getopts/" rel="alternate" type="text/html" title="关于Bash的内置getopts命令" /><published>2019-08-03T16:24:55+00:00</published><updated>2019-08-03T16:24:55+00:00</updated><id>https://thawk.github.io/%E8%BD%AF%E4%BB%B6/bash-getopts</id><content type="html" xml:base="https://thawk.github.io/%E8%BD%AF%E4%BB%B6/bash-getopts/">&lt;p&gt;一直以来，我都是用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getopt&lt;/code&gt;为shell脚本进行命令行参数解析，一路也都工作得很好。直到我遇上了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MacOS&lt;/code&gt;。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getopt&lt;/code&gt;是一个单独的命令，在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MacOS&lt;/code&gt;上的版本和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Linux&lt;/code&gt;上的不同，用法并不兼容，导致命令行脚本在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MacOS&lt;/code&gt;下工作不正常。&lt;/p&gt;

&lt;p&gt;为了解决问题，在网上搜了相关问题，发现有两种主要解决办法：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;安装并使用gnu版本的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getopt&lt;/code&gt;&lt;/p&gt;

    &lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;gnu-getopt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;在安装后，可以：&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;
        &lt;p&gt;用gnu版本代替内置版本&lt;/p&gt;

        &lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;brew &lt;span class=&quot;nb&quot;&gt;link&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--force&lt;/span&gt; gnu-getopt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;使用时指定&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getopt&lt;/code&gt;的绝对路径，如&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$(brew --prefix gnu-getopt)/bin/getopt&lt;/code&gt;。主要问题是这样就要求在脚本中指定&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getopt&lt;/code&gt;位置，在回到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Linux&lt;/code&gt;时并不通用，达不到兼容的目的。&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;通过环境变量&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FLAGS_GETOPT_CMD&lt;/code&gt;指定&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getopt&lt;/code&gt;位置，可以放到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.bashrc&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.zshrc&lt;/code&gt;之类的配置文件中。&lt;/p&gt;

        &lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;FLAGS_GETOPT_CMD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;brew &lt;span class=&quot;nt&quot;&gt;--prefix&lt;/span&gt; gnu-getopt&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/bin/getopt&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;p&gt;这样的好处是在脚本中只要正常使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getopt&lt;/code&gt;即可，完美兼容&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Linux&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MacOS&lt;/code&gt;。&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bash&lt;/code&gt;内置的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getopts&lt;/code&gt;命令&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bash&lt;/code&gt;内置了一个&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getopts&lt;/code&gt;命令，可以跨系统使用。但这个内置命令不支持长参数（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--long&lt;/code&gt;），不如独立的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getopt&lt;/code&gt;命令好用。然而&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MacOS&lt;/code&gt;中的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getopt&lt;/code&gt;也是不支持长参数的，所以问题也不算大，起码达到了兼容的目标。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;经过比较，出于提高脚本兼容性、减少对第三方包依赖的考虑，鉴于自己的脚本并不是那么复杂，并不需要很复杂的参数，使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bash&lt;/code&gt;内置的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getopts&lt;/code&gt;命令也已经足够了，所以就把脚本中的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getopt&lt;/code&gt;换成&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;getopts&lt;/code&gt;，Perfect！&lt;/p&gt;

&lt;p&gt;以下是我自己使用的&lt;a href=&quot;https://github.com/SirVer/ultisnips&quot;&gt;ultisnips&lt;/a&gt; snippet，方便复用。&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-snippet&quot;&gt;snippet getopts &quot;bash builtin getopts&quot; b
__ScriptVersion=&quot;${1:version}&quot;

EchoUsage()
{
    echo &quot;
Usage: $(basename &quot;\$0&quot;) [options] [--]

    Options:
        -h|help       Display this message
        -V|version    Display script version
        -v|verbose    Display more verbose log
        -t|test &amp;lt;val&amp;gt; A testing argument
&quot; &amp;gt;&amp;amp;2
}

VERBOSE=
while getopts &quot;:hVvt:&quot; opt; do
    case $opt in
        h|help)
            EchoUsage
            exit 0
            ;;
        V|version)
            echo &quot;$${1:(basename $0)} -- Version $__ScriptVersion&quot;
            exit 0
            ;;
        v|verbose)
            VERBOSE=&quot;${VERBOSE}1&quot;
            ;;
        t|test)
            echo &quot;Testing argument: '$OPTARG' at position $OPTIND&quot;
            ;;
        * )
            echo -e &quot;\n  Option does not exist : '$OPTARG' at position $OPTIND\n&quot;
            EchoUsage
            exit 1
            ;;
    esac
done
shift $(($OPTIND-1))

$0
endsnippet
&lt;/code&gt;&lt;/pre&gt;</content><author><name>thawk</name></author><category term="软件" /><category term="shell" /><summary type="html">一直以来，我都是用getopt为shell脚本进行命令行参数解析，一路也都工作得很好。直到我遇上了MacOS。getopt是一个单独的命令，在MacOS上的版本和Linux上的不同，用法并不兼容，导致命令行脚本在MacOS下工作不正常。</summary></entry><entry><title type="html">为什么我会使用VIM？</title><link href="https://thawk.github.io/%E6%9D%82%E8%B0%88/why-vim/" rel="alternate" type="text/html" title="为什么我会使用VIM？" /><published>2019-07-13T21:47:28+00:00</published><updated>2019-07-13T21:47:28+00:00</updated><id>https://thawk.github.io/%E6%9D%82%E8%B0%88/why-vim</id><content type="html" xml:base="https://thawk.github.io/%E6%9D%82%E8%B0%88/why-vim/">&lt;p&gt;知乎可能知道我用Vim，最近给我推了几篇关于Vim的文章，一些关于在9102年还应不应该使用Vim的争论。看了之后，想起自己入坑的经历，所以分享一下。至于有木有人看到，那都不重要了。&lt;/p&gt;

&lt;h3 id=&quot;黄金时代&quot;&gt;黄金时代&lt;/h3&gt;

&lt;p&gt;想当年，我主要是进行Visual C++下的开发，那时候用得还是普通PC作为开发机，自然就在Visual Studio进行开发工作了。编辑、编译、调试一条龙，很爽有没有？当时虽然也听说过神之编辑器Emacs和编辑器之神Vim，但下载试用一下，看看教程的厚度就放弃了，木有什么动力去学习其中之一。&lt;/p&gt;

&lt;p&gt;那时候，除了写代码外，我有时还要处理一些文本，比如整理一下数据、处理一下测试结果之类的。作为一个合格（懒惰）的码农，只要重复超过10次（或者更少？），我就会想办法看能不能有批处理的手段。也就是在这样的情况下，接触到了正则表达式，一时间惊为天人，用来整理数据是多么的方便啊！当时也没有VSCode、Sublime Text什么的，对于普通的编辑工作主要就是在Ultra Edit上进行。Ultra Edit既支持正则表达式，又支持列编辑模式，对于大文件的编辑也得心应手，配置配置，语法高亮和列出文件中的函数也不在话下，只能说“真香”。&lt;/p&gt;

&lt;p&gt;就这样，用Visual Studio写代码，用Ultra Edit编辑其他文件，很是过了一段舒心的日子。&lt;/p&gt;

&lt;h3 id=&quot;白银时代&quot;&gt;白银时代&lt;/h3&gt;

&lt;p&gt;以当年那份躁动的心，好日子过久了，慢慢就不满足现状了。先是原来用的Visual Stuio版本太老了，需要升级到更新一点的版本，升级后发现很多快捷键都变了，有点不适应。然后发现Ultra Edit也有新的版本，自然也不甘落后了。问题就出在新版本的Ultra Edit上，升级后发现那个版本的正则表达式总有这样那样的问题，用起来没有了原来行云流水的感觉，忍了一段时间后实在是忍无可忍，决定更换编辑器。&lt;/p&gt;

&lt;p&gt;用什么编辑器好呢？使用了其他编辑器，用起来都差不多，不过快捷键和Ultra Edit很不一样，又要重新熟悉。这时候就想起了我们编辑器之神，既然都要花费精力，何不尝试一下与Emacs以及“其他编辑器”三足鼎立的Vim呢？于是花了点时间熟悉了Vim的操作，顿时感觉相见恨晚，Vim中的正则表达式引擎可不是Ultra Edit能比的，Visual C++就更不用说了。在度过初期的适应期后，发现对于文本文件的处理效率比原来更高，只有一个字，“爽”。&lt;/p&gt;

&lt;p&gt;当时除了继续维护Visual C++的程序外，还要开发&lt;a href=&quot;https://en.wikipedia.org/wiki/Tandem_Computers&quot;&gt;Tandem&lt;/a&gt;上的C程序，这些程序虽然也是C程序，但多了一些非标扩展，程序也不算长而且不能在Visual C++上编译，所以本来就要在编辑器上进行一些代码编写工作，干脆把coding任务也转移到Vim上。只要在Vim中配置一下编译命令，对于Visual C++程序也是能正常编译并且能跳转到编译出错的地方，所以所有编辑工作基本上转移到Vim上。&lt;/p&gt;

&lt;p&gt;这一阶段随着我的工作从Visual C++和Tandem转移到Linux Server之后达到巅峰，作为主力编辑器，自己全手撸了超过3000行的&lt;a href=&quot;https://github.com/thawk/dotvim&quot;&gt;Vim配置&lt;/a&gt;，包含好像超过80个插件，什么配置管理、tag跳转、clang代码跳转应有尽有。而且为了适应内网、外网，Linux、Windows、FreeBSD等不同环境、不同性能限制，在配置中对插件进行了分组管理，从简便高效的最小配置到以IDE为目标的配置都可以自定义。当时这份配置作为项目组的非官方标准配置被大家广泛采用，在我久不维护的现在，还有人在低版本的Vim上使用这份配置。&lt;/p&gt;

&lt;h3 id=&quot;黑铁时代&quot;&gt;黑铁时代&lt;/h3&gt;

&lt;p&gt;手撸配置一时爽，一直撸一直爽。自己的配置当然是最符合自己的习惯的，用起来也是最顺手的。但随着Vim版本的不断升级，特别是Vim 8.0版本的推出，新增了异步机制，很多插件都有了更好用的替代品，特别是包管理软件也要更新换代，各种插件加载、配置的写法都得更新。这时候感觉有点跟不上节奏，懒得更新了。这时候，发现了&lt;a href=&quot;https://spacevim.org&quot;&gt;SpaceVim&lt;/a&gt;，一份现成的、结构化的配置，干脆弃用了自己的配置，转用SpaceVim，并进行了一些&lt;a href=&quot;https://github.com/thawk/dotspacevim&quot;&gt;定制&lt;/a&gt;。此后就比较佛系了，有问题就提个issue，能解决就提个Pull Request，个性化的需求就放到自己的配置中，一切回归平淡。唯一不变的就是Vim的主力编辑器地位仍然稳固。&lt;/p&gt;

&lt;p&gt;现在唯一的问题就是SpaceVim对Vim最低版本有要求，而我们的主力开发环境还在RHEL 6上，所以只能自己编译一套新版本的Vim才能用。不过对于开发服务器基本固定的我来说，折腾一次之后也不会有太大的问题了。&lt;/p&gt;

&lt;h3 id=&quot;总结&quot;&gt;总结&lt;/h3&gt;

&lt;p&gt;正如知乎上很多评论说的，既然已经习惯了Vim，Vim又能基本满足要求，那么有什么理由更换为其他工具，再学习一套或者多套快捷键呢？&lt;/p&gt;

&lt;p&gt;在9102年的今天、在正版化要求越来越高的今天，IDE在不断式微，以VSCode为代表的编辑器正在占据越来越大的版图。既然都是编辑器加插件，现在也有了SpaceVim之类的现成配置，已经不需要手撸配置了，Vim的门槛也比以前低了不少。随着微软&lt;a href=&quot;https://microsoft.github.io/language-server-protocol/&quot;&gt;Language Server Protocol&lt;/a&gt;的推出，以往只有IDE能实现的精确的上下文补全、文档提示、重构等功能都可以通过LSP接入到编辑器中。Vim也是有支持LSP的插件的。与其换到其他编辑器中，使用半吊子的Vim模式，何不继续使用越来越好用的Vim呢？&lt;/p&gt;

&lt;p&gt;其实还有一个不太具有代表性的原因，现在随着对信息安全的重视，我们的内网早已从普通PC机转到云端，用一个瘦客户端访问一台虚机桌面。也不知在一台物理服务器上分配了多少虚机，反正那性能是不用期待太多的，反正全新拉一次代码（含Boost库）的时间得几十分钟。而我们作为开发机的Linux服务器是一台24核的物理服务器，24进程并发编译的速度可是杠杠滴。&lt;/p&gt;

&lt;p&gt;当然，随着VSCode重磅推出远程功能，现在用VSCode也是很方便的。不过，给个换的理由？当然了，在这个年代，我也是不会劝人入Vim坑的了，一般我都告诉新人，VSCode很好用，某某同事精通VSCode的配置。。。&lt;/p&gt;</content><author><name>thawk</name></author><category term="杂谈" /><category term="vim" /><summary type="html">知乎可能知道我用Vim，最近给我推了几篇关于Vim的文章，一些关于在9102年还应不应该使用Vim的争论。看了之后，想起自己入坑的经历，所以分享一下。至于有木有人看到，那都不重要了。</summary></entry><entry><title type="html">RFC 2119 文档中定义要求级别的关键字</title><link href="https://thawk.github.io/%E6%9D%82%E8%B0%88/rfc-2119-requirement-levels/" rel="alternate" type="text/html" title="RFC 2119 文档中定义要求级别的关键字" /><published>2019-07-09T16:07:26+00:00</published><updated>2019-07-09T16:07:26+00:00</updated><id>https://thawk.github.io/%E6%9D%82%E8%B0%88/rfc-2119-requirement-levels</id><content type="html" xml:base="https://thawk.github.io/%E6%9D%82%E8%B0%88/rfc-2119-requirement-levels/">&lt;p&gt;在看一份协议规范文档时，文档中提到其用语符合&lt;a href=&quot;https://tools.ietf.org/html/rfc2119&quot;&gt;RFC 2119&lt;/a&gt;，因此查阅了这份RFC，记录做个笔记：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;有五种不同的要求级别：&lt;/p&gt;

    &lt;ol&gt;
      &lt;li&gt;
        &lt;p&gt;&lt;strong&gt;MUST&lt;/strong&gt;/&lt;strong&gt;REQUIRED&lt;/strong&gt;/&lt;strong&gt;SHALL&lt;/strong&gt;&lt;/p&gt;

        &lt;p&gt;表明这是&lt;strong&gt;必须&lt;/strong&gt;的特性。&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;&lt;strong&gt;MUST NOT&lt;/strong&gt;/&lt;strong&gt;SHALL NOT&lt;/strong&gt;&lt;/p&gt;

        &lt;p&gt;表明这是被&lt;strong&gt;严格禁止&lt;/strong&gt;的特性。&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;&lt;strong&gt;SHOULD&lt;/strong&gt;/&lt;strong&gt;RECOMMENDED&lt;/strong&gt;&lt;/p&gt;

        &lt;p&gt;表明这是被&lt;strong&gt;推荐&lt;/strong&gt;的特性，大部分情况下应采纳。如不采纳，应认真评估。&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;&lt;strong&gt;SHOULD NOT&lt;/strong&gt;/&lt;strong&gt;NOT RECOMMENDED&lt;/strong&gt;&lt;/p&gt;

        &lt;p&gt;表明这是&lt;strong&gt;不推荐&lt;/strong&gt;的特性，一般情况下不应使用。如要使用，应认真评估。&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;&lt;strong&gt;MAY&lt;/strong&gt;/&lt;strong&gt;OPTIONAL&lt;/strong&gt;&lt;/p&gt;

        &lt;p&gt;表明这是&lt;strong&gt;可选&lt;/strong&gt;的特性。但实现者必须能对接实现或不实现这个特性的另一方。&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;除了定义了上述关键字的用法外，RFC中还规定采用了本规范的文档，应该在靠近文档开始处加入一段声明：&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL
NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;,  &quot;MAY&quot;, and
&quot;OPTIONAL&quot; in this document are to be interpreted as described in
RFC 2119.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;本规范并未要求上述关键字的大小写形式，但&lt;a href=&quot;https://tools.ietf.org/html/rfc8174&quot;&gt;RFC 8174&lt;/a&gt;在此基础上要求上述关键字必须是全大写的才有特殊含义。声明文字也改为：&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;The key words &quot;MUST&quot;, &quot;MUST NOT&quot;, &quot;REQUIRED&quot;, &quot;SHALL&quot;, &quot;SHALL
NOT&quot;, &quot;SHOULD&quot;, &quot;SHOULD NOT&quot;, &quot;RECOMMENDED&quot;, &quot;NOT RECOMMENDED&quot;,
&quot;MAY&quot;, and &quot;OPTIONAL&quot; in this document are to be interpreted as
described in BCP 14 [RFC2119] [RFC8174] when, and only when, they
appear in all capitals, as shown here.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;</content><author><name>thawk</name></author><category term="杂谈" /><category term="规范" /><summary type="html">在看一份协议规范文档时，文档中提到其用语符合RFC 2119，因此查阅了这份RFC，记录做个笔记：</summary></entry><entry><title type="html">对于容器技术应用于开发的一点思考</title><link href="https://thawk.github.io/%E6%9D%82%E8%B0%88/container-for-dev/" rel="alternate" type="text/html" title="对于容器技术应用于开发的一点思考" /><published>2019-07-05T11:58:52+00:00</published><updated>2019-07-05T11:58:52+00:00</updated><id>https://thawk.github.io/%E6%9D%82%E8%B0%88/container-for-dev</id><content type="html" xml:base="https://thawk.github.io/%E6%9D%82%E8%B0%88/container-for-dev/">&lt;p&gt;以&lt;a href=&quot;https://www.docker.com/&quot;&gt;Docker&lt;/a&gt;为代表的容器技术早已成为热门，按说也没什么可以讨论的。但我们一直还没用上容器技术，为什么呢？是不是容器技术真的不适合我们呢？这倒值得探讨一下。&lt;/p&gt;

&lt;p&gt;传统上，容器技术更多用于&lt;a href=&quot;https://en.wikipedia.org/wiki/DevOps&quot;&gt;DevOps&lt;/a&gt;，利用其实现快速交付的能力，实现快速部署、方便的迁移和故障恢复，虚拟化技术也能顺便节省一点资源。而我们的应用不追求或者说对快速部署的追求没有这么高，也不太需要节省资源，应用都是直接运行在物理机上，&lt;a href=&quot;https://en.wikipedia.org/wiki/Disaster_recovery#Recovery_Point_Objective&quot;&gt;RPO&lt;/a&gt;为0的高可用目标也不是通过容器集群方式提供。所以我们传统上对容器没有太多想法，也没有用到容器。&lt;/p&gt;

&lt;p&gt;但我们是不是真的用不上容器技术呢？我觉得不是的。我觉得对我们来说，容器技术至少能在两方面发挥作用：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;统一构建环境。&lt;/p&gt;

    &lt;p&gt;我们主要在Linux下进行开发，更具体点，主要支持&lt;a href=&quot;https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux&quot;&gt;红帽RHEL&lt;/a&gt;。在构建过程中，我们要保证系统用到的库文件、编译器版本都和生产一致。而难免有些库文件或公共组件存在多个版本，我们在不同分支上可能需要使用不同的版本，所以不适合直接安装到系统中。在这时候，一个配置好编译器、各种开发库的容器就是一个很好的选择。无论我们用的是什么环境，甚至可以选择其他更顺手的Linux版本，编译出来的就是我们想要的组合。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;统一开发环境。&lt;/p&gt;

    &lt;p&gt;现代的开发环境除了大型的IDE外，还有&lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;VSCode&lt;/a&gt;、&lt;a href=&quot;https://www.vim.org/&quot;&gt;Vim&lt;/a&gt;之类比较轻量的开源环境可供选择，特别是在越来越重视正版化的现在，又贵又笨重的IDE正在逐渐淡出。特别在微软推出&lt;a href=&quot;https://microsoft.github.io/language-server-protocol/&quot;&gt;LSP&lt;/a&gt;（Language Server Protocol）之后，上下文补全、跳转、重构等功能不再是IDE的专利，各种轻量级环境配合LSP也能满足日常的需要。&lt;/p&gt;

    &lt;p&gt;轻量级的开发环境一般都会提供多种多样的插件，配合合适的插件、配合Language Server变成一个好用的环境。在这过程中，免不了要安装各种支持工具（&lt;a href=&quot;http://ctags.sourceforge.net/&quot;&gt;ctags&lt;/a&gt;、&lt;a href=&quot;https://www.gnu.org/software/global/&quot;&gt;gtags&lt;/a&gt;、&lt;a href=&quot;https://github.com/junegunn/fzf&quot;&gt;fzf&lt;/a&gt;），可能还要安装Python、Language Server等。如果每个人都自己研究一番，未免效率太低了。另外，随着大家对安全的看中，不少单位都实行内外网隔离，在开发网无法直接访问互联网，安装第三方工具变得相当麻烦。因此可以把配置好的开发环境作为一个容器，把用到的工具、软件、插件全部封装到容器内，实现一次配置，到处使用，大大提高开发效率。&lt;/p&gt;

    &lt;p&gt;可能有童鞋会觉得容器是不是只能封装Vim、Emacs之类基于终端的工具呢？其实不是的，只要在宿主机上装一个XServer就可以运行。&lt;a href=&quot;https://blog.jessfraz.com/post/docker-containers-on-the-desktop/&quot;&gt;这里&lt;/a&gt;能找到一些例子。&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;容器能干很多事情。不过对于还在RHEL 6上工作的我们来说，要支持Docker还有那么一点麻烦，还是期待晚一点转移到RHEL 7的时候好好用用Docker吧。&lt;/p&gt;</content><author><name>thawk</name></author><category term="杂谈" /><category term="容器" /><summary type="html">以Docker为代表的容器技术早已成为热门，按说也没什么可以讨论的。但我们一直还没用上容器技术，为什么呢？是不是容器技术真的不适合我们呢？这倒值得探讨一下。</summary></entry><entry><title type="html">高可用之冷备、温备和热备</title><link href="https://thawk.github.io/%E6%9E%B6%E6%9E%84/high-availability-cold-warm-hot/" rel="alternate" type="text/html" title="高可用之冷备、温备和热备" /><published>2019-06-19T11:55:17+00:00</published><updated>2019-06-19T11:55:17+00:00</updated><id>https://thawk.github.io/%E6%9E%B6%E6%9E%84/high-availability-cold-warm-hot</id><content type="html" xml:base="https://thawk.github.io/%E6%9E%B6%E6%9E%84/high-availability-cold-warm-hot/">&lt;p&gt;今天与同事讨论了什么是冷备、什么是热备，顺便整理一下。&lt;/p&gt;

&lt;p&gt;根据IBM社区的一篇&lt;a href=&quot;https://www.ibm.com/developerworks/community/blogs/RohitShetty/entry/high_availability_cold_warm_hot?lang=en&quot;&gt;文章&lt;/a&gt;，集群（Clustering）是为了达成高可用，而在软件、硬件和数据上引入了冗余。根据在软件上的不同冗余程度，可以分为几种：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;冷备（Code Standby）&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;备份点平时不启动（甚至可以在主节点首次故障时才进行部署），当主节点故障时，需要先恢复备份点的数据，再启动备份组件。&lt;/li&gt;
      &lt;li&gt;主备节点间按需进行数据同步。&lt;/li&gt;
      &lt;li&gt;主备切换时间通常是几个小时。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;温备（Warm Standby）&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;备份点提前部署好，但备份组件平时不启动。当主节点故障时，启动备份节点上的备份组件。&lt;/li&gt;
      &lt;li&gt;切换过程通常由集群软件自动执行。&lt;/li&gt;
      &lt;li&gt;数据定期在主备节点间通过复制或共享盘进行同步。&lt;/li&gt;
      &lt;li&gt;主备切换时间通常是几分钟。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;冷备（Hot Standby）&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;备份点提前部署好。备份组件启动但不处理数据或请求。&lt;/li&gt;
      &lt;li&gt;数据几乎实时镜像到备份点，主备系统将有一致的数据。&lt;/li&gt;
      &lt;li&gt;通常通过软件机制进行主备数据同步。&lt;/li&gt;
      &lt;li&gt;主备切换时间通常是几秒钟。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;多活（Active-Active）&lt;/strong&gt;或&lt;strong&gt;负载均衡（Load Balanced）&lt;/strong&gt;：
    &lt;ul&gt;
      &lt;li&gt;主备节点同时并行处理请求。&lt;/li&gt;
      &lt;li&gt;通过软件机制进行主备数据同步。&lt;/li&gt;
      &lt;li&gt;数据双向同步。&lt;/li&gt;
      &lt;li&gt;主备切换即时完成。&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;综合以上几种模式，区别主要在于备份节点、备份组件是否启动、是否提供服务，主备数据同步如何进行、数据落差有多大。体现出来的效果就是主备切换时间从几个小时到几分钟到几秒再到即时。&lt;/p&gt;

&lt;p&gt;不同高可用级别之间效果不同，要付出的代价当然也是不同的，需要在系统的要求、所需的技术和要付出的成本进行权衡。&lt;/p&gt;</content><author><name>thawk</name></author><category term="架构" /><category term="高可用" /><summary type="html">今天与同事讨论了什么是冷备、什么是热备，顺便整理一下。</summary></entry><entry><title type="html">为ConEmu下的命令行版本Vim配置SpaceVim的方法</title><link href="https://thawk.github.io/%E8%BD%AF%E4%BB%B6/vim-conemu/" rel="alternate" type="text/html" title="为ConEmu下的命令行版本Vim配置SpaceVim的方法" /><published>2019-06-17T18:37:51+00:00</published><updated>2019-06-17T18:37:51+00:00</updated><id>https://thawk.github.io/%E8%BD%AF%E4%BB%B6/vim-conemu</id><content type="html" xml:base="https://thawk.github.io/%E8%BD%AF%E4%BB%B6/vim-conemu/">&lt;p&gt;&lt;a href=&quot;https://conemu.github.io&quot;&gt;ConEmu&lt;/a&gt;是我目前正在使用的Windows下终端封装程序（实际用的是&lt;a href=&quot;https://cmder.net/&quot;&gt;Cmder&lt;/a&gt;），配合&lt;a href=&quot;https://mintty.github.io/&quot;&gt;mintty&lt;/a&gt;、&lt;a href=&quot;https://gitforwindows.org/&quot;&gt;Git Bash&lt;/a&gt;等，无论是通过ssh远程登录到服务器还是使用本地cmd/bash终端都非常方便。但缺省情况下，Vim在ConEmu中能用，但颜色不是很好看，和Linux/MacOS下的Vim形象相去甚远，所以基本上很少在Windows的命令行下直接使用Vim，更多的是使用Gvim/Neovim。为了改进这点，特地搜索了正确的配置方法，让Vim在ConEmu下也能顺畅地使用，方便在ConEmu命令行下直接用Vim编辑文本而不用切换到独立的程序中。&lt;/p&gt;

&lt;p&gt;根据&lt;a href=&quot;https://conemu.github.io/en/VimXterm.html&quot;&gt;ConEmu文档&lt;/a&gt;，需要满足以下条件：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;只支持部分版本。如Vim官方发布的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gvim##.exe&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim##w32.zip&lt;/code&gt;中的版本。Vim 7.x、8.x都可以；&lt;/li&gt;
  &lt;li&gt;Vim的可执行程序必须名为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vim.exe&lt;/code&gt;；&lt;/li&gt;
  &lt;li&gt;ConEmu配置中必须配置几个选项：
    &lt;ul&gt;
      &lt;li&gt;选中&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Features&lt;/code&gt;配置页面中的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Inject ConEmuHk&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ANSI X3.64 / xterm 256 colors&lt;/code&gt;（在我用的版本中没找到后者）；&lt;/li&gt;
      &lt;li&gt;选中&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Colors&lt;/code&gt;配置页面中的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TrueMod (24bit color) support&lt;/code&gt;；&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;使用一个支持&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Xterm color&lt;/code&gt;的配色方案，如&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;zenburn&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;onedark&lt;/code&gt;。&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;配置Vim&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;
        &lt;p&gt;对于普通Vim配置，可以在Vim配置中加上：&lt;/p&gt;

        &lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &amp;amp;&lt;span class=&quot;nb&quot;&gt;term&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'win32'&lt;/span&gt; &amp;amp;&amp;amp; &lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;$ConEmuANSI&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;termencoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;utf8
    &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;term&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;xterm
    &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;t_Co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;256&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; notermguicolors
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &amp;amp;&lt;span class=&quot;nb&quot;&gt;t_AB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;\e[48;5;%dm&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &amp;amp;&lt;span class=&quot;nb&quot;&gt;t_AF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;\e[38;5;%dm&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;colorscheme&lt;/span&gt; zenburn
&lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;由于我使用的是&lt;a href=&quot;https://spacevim.org/&quot;&gt;SpaceVim&lt;/a&gt;，因此在自己的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;myspacevim##before()&lt;/code&gt;中加入：&lt;/p&gt;

        &lt;div class=&quot;language-vim highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &amp;amp;&lt;span class=&quot;nb&quot;&gt;term&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;'win32'&lt;/span&gt; &amp;amp;&amp;amp; &lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;$ConEmuANSI&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;termencoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;utf8
    &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;term&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;xterm
    &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;t_Co&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;256&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &amp;amp;&lt;span class=&quot;nb&quot;&gt;t_AB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;\e[48;5;%dm&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &amp;amp;&lt;span class=&quot;nb&quot;&gt;t_AF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;\e[38;5;%dm&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;g:spacevim_enable_guicolors&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;g:spacevim_colorscheme_default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;zenburn&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;endif&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;        &lt;/div&gt;

        &lt;p&gt;由于使用了SpaceVim，因此有两个配置改为修改SpaceVim配置变量而不是直接改动Vim的设置，避免被SpaceVim覆盖。&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;在运行Vim时，指定终端编码为UTF-8:&lt;/p&gt;

    &lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;chcp 65001
vim
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;通过上述配置，实测zenburn/onedark/monokai/molokai等配色方案都能正常显示，但&lt;a href=&quot;https://github.com/icymind/NeoSolarized&quot;&gt;NeoSolarized&lt;/a&gt;显示不正常。&lt;/p&gt;</content><author><name>thawk</name></author><category term="软件" /><category term="Vim" /><category term="ConEmu" /><category term="SpaceVim" /><summary type="html">ConEmu是我目前正在使用的Windows下终端封装程序（实际用的是Cmder），配合mintty、Git Bash等，无论是通过ssh远程登录到服务器还是使用本地cmd/bash终端都非常方便。但缺省情况下，Vim在ConEmu中能用，但颜色不是很好看，和Linux/MacOS下的Vim形象相去甚远，所以基本上很少在Windows的命令行下直接使用Vim，更多的是使用Gvim/Neovim。为了改进这点，特地搜索了正确的配置方法，让Vim在ConEmu下也能顺畅地使用，方便在ConEmu命令行下直接用Vim编辑文本而不用切换到独立的程序中。</summary></entry><entry><title type="html">C++函数声明中要不要用右值引用？</title><link href="https://thawk.github.io/c++/rvalue-parameter-of-function/" rel="alternate" type="text/html" title="C++函数声明中要不要用右值引用？" /><published>2019-06-14T08:57:49+00:00</published><updated>2019-06-14T08:57:49+00:00</updated><id>https://thawk.github.io/c++/rvalue-parameter-of-function</id><content type="html" xml:base="https://thawk.github.io/c++/rvalue-parameter-of-function/">&lt;p&gt;在一次代码评审时，看到一个成员函数使用了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;const T&amp;amp;&lt;/code&gt;，不假思索地就建议使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T&lt;/code&gt;传值，在函数内用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::move&lt;/code&gt;进行移动。之后有同事问我，不是应该用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;func(T&amp;amp;&amp;amp;)&lt;/code&gt;吗？一时间感觉脑子不好用，难道一段时间不用，哪里搞错了？赶紧上网搜索答案。&lt;/p&gt;

&lt;h2 id=&quot;应该使用传值吗&quot;&gt;应该使用传值吗？&lt;/h2&gt;

&lt;p&gt;在STL中，可以看到很多地方都同时提供&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;const T&amp;amp;&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T&amp;amp;&amp;amp;&lt;/code&gt;两种重载，分别对应参数为左值和右值两种情况。看来这样做是标准做法吧。但这样一来，基本相同的逻辑要重复写两次。说好的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DRY&lt;/code&gt;（&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Don't Repeat Yourself&lt;/code&gt;）原则呢？&lt;/p&gt;

&lt;p&gt;在&lt;a href=&quot;https://stackoverflow.com/questions/7592630/is-pass-by-value-a-reasonable-default-in-c11&quot;&gt;链接1&lt;/a&gt;、&lt;a href=&quot;https://stackoverflow.com/questions/18673658/should-i-always-move-on-sink-constructor-or-setter-arguments&quot;&gt;链接2&lt;/a&gt;中，都看到有答主推荐如果函数内需要保存参数的一个拷贝，就用传值。&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;t_&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;move&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// ...&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这样，调用者可以决定是否使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::move&lt;/code&gt;放弃传入参数的所有权。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;如果调用者放弃所有权，整个过程中不发生拷贝；&lt;/li&gt;
  &lt;li&gt;如果调用者不放弃所有权，无论用什么方式，还是会发生一次拷贝。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;这样看来，因此传值并没有引入额外的开销，还避免了同时提供&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;const T&amp;amp;&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T&amp;amp;&amp;amp;&lt;/code&gt;类型参数的两个重载的麻烦，完美！&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// copy from lvalue&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{});&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// (potential) move from prvalue&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;move&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// (potential) move from xvalue&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;还有什么选择&quot;&gt;还有什么选择？&lt;/h2&gt;

&lt;p&gt;传值看上去很美。不过，STL是怎么回事？难道标准委员会的人看不到这点？我们还是继续找答案吧。&lt;/p&gt;

&lt;p&gt;在CppCon 2014上，Herb Sutter发表了题为“Back to the Basics! Essentials of Modern C++ Style”的&lt;a href=&quot;https://github.com/CppCon/CppCon2014/tree/master/Presentations/Back%20to%20the%20Basics!%20Essentials%20of%20Modern%20C%2B%2B%20Style&quot;&gt;演讲&lt;/a&gt;（&lt;a href=&quot;http://www.youtube.com/watch?v=xnqTKD8uD64&quot;&gt;视频在此&lt;/a&gt;），谈到了我们关心的问题。&lt;/p&gt;

&lt;p&gt;在演讲中，Herb Sutter谈到&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;对于输出参数或者输入/输出的参数，用函数返回值或者用左值引用参数&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T&amp;amp;&lt;/code&gt;即可；&lt;/li&gt;
  &lt;li&gt;对于小对象（如基本数值类型）和不能拷贝的对象，传值即可；&lt;/li&gt;
  &lt;li&gt;对于大的输入参数：
    &lt;ul&gt;
      &lt;li&gt;如果函数内不需要保留，直接用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;const T&amp;amp;&lt;/code&gt;即可；&lt;/li&gt;
      &lt;li&gt;如果函数内需要保留一份，则：
        &lt;ol&gt;
          &lt;li&gt;和C++ 98一样，优先使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;const T&amp;amp;&lt;/code&gt;；&lt;/li&gt;
          &lt;li&gt;为了增加优化机会，可以在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;const T&amp;amp;&lt;/code&gt;基础上，增加右值引用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T&amp;amp;&amp;amp;&lt;/code&gt;的重载；&lt;/li&gt;
          &lt;li&gt;如果可以接受代码必须放在头文件中，并且不能作为虚函数，也可以考虑用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;forward reference&lt;/code&gt;，即&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;universal reference&lt;/code&gt;。&lt;/li&gt;
        &lt;/ol&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;前面几点都没有什么问题，和C++ 98是一样的。分歧在于在对于大的输入参数，且函数内需要在保存一份时为什么不直接传值？&lt;/p&gt;

&lt;h2 id=&quot;传值有什么问题&quot;&gt;传值有什么问题？&lt;/h2&gt;

&lt;p&gt;传值在很多时候是可以的，但Herb Sutter指出了重要的一点，也是最重要的一点：对于要进行内存分配、而调用者又不希望转移所有权的参数，传值意味着&lt;strong&gt;100%&lt;/strong&gt;会进行一次内存分配。初看起来，这不是很正常吗？既然调用者不转移所有权，而被调的地方又需要保留一份，难道不是&lt;strong&gt;必须&lt;/strong&gt;进行内存分配？&lt;/p&gt;

&lt;p&gt;不是的！无论是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::string&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::vector&lt;/code&gt;还是其他对象，在目标对象有足够空间保存新的值时，是不需要重新进行内存分配的。比如原来的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::string&lt;/code&gt;对象能容纳100字节，赋给这个对象50字节的新值时，并不会先释放原来100字节的内存再分配50字节的新内存，而是会直接复制到原来100字节的内存中，并标记其长度 为50字节。这时候是不需要内存分配的。&lt;/p&gt;

&lt;p&gt;Herb Sutter在演讲中提到，现实情况中，远低于50%的对象拷贝会触发内存分配。因此在这样的情况下，把&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;常量引用 + 复制&lt;/code&gt;改为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;传值 + 移动&lt;/code&gt;，其效率不是不变而是降低，还降低很多。&lt;/p&gt;

&lt;h2 id=&quot;结论&quot;&gt;结论&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;一般情况下用常量引用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;const T&amp;amp;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;确实有优化必要时可以增加一个接受右值引用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T&amp;amp;&amp;amp;&lt;/code&gt;的重载&lt;/li&gt;
  &lt;li&gt;在构造函数等不涉及利用目标对象原有空间（必须从零开始构造）的情况下，可以传值，以避免在多参数函数中，每个参数都可能是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;const T&amp;amp;&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;T&amp;amp;&amp;amp;&lt;/code&gt;造成的组合爆炸&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;回头看看，我遇到的那个场景类似于构造函数，传值是可以的。But, however，这个场景基本上只在初始化时调用，并没有优化的必要，直接用最简单的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;const T&amp;amp;&lt;/code&gt;也是没问题的，看来是自己想多了 ╮（﹀＿﹀）╭&lt;/p&gt;</content><author><name>thawk</name></author><category term="C++" /><category term="右值引用" /><summary type="html">在一次代码评审时，看到一个成员函数使用了const T&amp;amp;，不假思索地就建议使用T传值，在函数内用std::move进行移动。之后有同事问我，不是应该用func(T&amp;amp;&amp;amp;)吗？一时间感觉脑子不好用，难道一段时间不用，哪里搞错了？赶紧上网搜索答案。</summary></entry><entry><title type="html">开始写博客了</title><link href="https://thawk.github.io/%E6%9D%82%E8%B0%88/start-blogging/" rel="alternate" type="text/html" title="开始写博客了" /><published>2019-06-06T23:04:17+00:00</published><updated>2019-06-06T23:04:17+00:00</updated><id>https://thawk.github.io/%E6%9D%82%E8%B0%88/start-blogging</id><content type="html" xml:base="https://thawk.github.io/%E6%9D%82%E8%B0%88/start-blogging/">&lt;p&gt;当了多年码农，也码出了不少代码，在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;github&lt;/code&gt;上也记录了不少&lt;a href=&quot;https://github.com/thawk/wiki/wiki&quot;&gt;内容&lt;/a&gt;。回头看看，这些内容作为备忘、速查也是挺好的，但实在过于简略，相当于&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cheatsheet&lt;/code&gt;的水平，时间一长就记不起来具体细节。所以起了写博客的念头，至少把一些过程可以稍稍记录一下。&lt;/p&gt;

&lt;p&gt;主要就是技术方面的内容了，不一定有什么高深的东西，毕竟自己是做应用不是做研究的。&lt;/p&gt;</content><author><name>thawk</name></author><category term="杂谈" /><category term="杂谈" /><summary type="html">当了多年码农，也码出了不少代码，在github上也记录了不少内容。回头看看，这些内容作为备忘、速查也是挺好的，但实在过于简略，相当于cheatsheet的水平，时间一长就记不起来具体细节。所以起了写博客的念头，至少把一些过程可以稍稍记录一下。</summary></entry></feed>