1.1.1 系统默认代码页
在我们熟悉的简体中文系统上,系统默认代码页是936,对应的编码是GB2312,后来的GBK和GB18030在GB2312的基础上作了扩充,这里我们不管这么多,直接把CP936和GBK当作等同的说法。
系统默认代码页不是一成不变的,而是随着语言和区域的不同而变化。在许多西欧国家,系统默认代码页是1252,在繁体中文系统上,系统默认代码页是950,对应的编码是Big5,即著名的大五码,相信老玩家们对这个编码一定不会陌生。
即便在同一台计算机上,系统默认代码页也是可以通过语言和区域设置修改的。从Windows 10 version 1803 (10.0.17134.0)开始,Windows支持把UTF-8设为系统默认代码页,不难看出有向Linux靠拢的意思。

系统默认代码页对C程序中的两个东西有显著的影响,一个是程序参数argv,一个是setlocale函数。
在main函数中,形参argv的声明长这样:
char *argv[]
argv是一个数组,它的每个元素都是指向多字节字符串的指针(除了argv[argc]是空指针),这些多字节字符串的编码就是系统默认代码页所对应的编码。
举两个例子:
假设有一个C程序prog.exe,在简体中文系统上以
prog 李白
启动该程序,那么argv[1]的前4个元素是:{0xc0, 0xee, 0xb0, 0xd7}。

如果在繁体中文系统上以同样的方式启动该程序,那么argv[1]的前4个元素是:{0xa7, 0xf5, 0xa5, 0xd5}。

请注意,以上两个示意图是对实际过程的一种高度简化的描述,程序参数传递的过程实际上非常复杂,其中涉及到多次编码转换,远非三言两语能说得明白。
至于setlocale函数,C标准对它有这样的描述:

我们感兴趣的是以空字符串为参数调用setlocale的情况:
setlocale(LC_ALL, "");
如果系统默认代码页是936,这相当于
setlocale(LC_ALL, ".936");
如果系统默认代码页是950,则相当于
setlocale(LC_ALL, ".950");